{"id":1532,"date":"2022-10-04T12:54:48","date_gmt":"2022-10-04T10:54:48","guid":{"rendered":"https:\/\/www.loicmathieu.fr\/wordpress\/?p=1532"},"modified":"2022-10-04T12:58:40","modified_gmt":"2022-10-04T10:58:40","slug":"tester-une-java-google-cloud-function","status":"publish","type":"post","link":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/tester-une-java-google-cloud-function\/","title":{"rendered":"Testing a Java Google Cloud Function"},"content":{"rendered":"<p>Until recently, testing a Google Cloud Function written in Java could be done via the invoker provided by the Google Cloud Functions SDK but not via a unit test. But this changed recently!<\/p>\n<p>Let&#8217;s take the following HTTP function as an example:<\/p>\n<pre>\npublic class HelloHttpFunction implements HttpFunction { \n    @Override\n    public void service(HttpRequest httpRequest, HttpResponse httpResponse) \n            throws Exception { \n        Writer writer = httpResponse.getWriter();\n        writer.write(\"Hello World\");\n    }\n}\n<\/pre>\n<p>After packaging the function into an \u00fcber JAR, we can download the Google Cloud function invoker via the following Maven command:<\/p>\n<pre>\nmvn dependency:copy \\\n  -Dartifact='com.google.cloud.functions.invoker:java-function-invoker:1.1.1' \\\n  -DoutputDirectory=.\n<\/pre>\n<p>Then use it to start the function locally:<\/p>\n<pre>\njava -jar java-function-invoker-1.1.1.jar \\\n  --classpath target\/hello-world.jar \\\n  --target org.example.HelloHttpFunction\n<\/pre>\n<p>Our function is then testable on port 8080.<\/p>\n<p>Alas, this is not practical from a continuous integration perspective where we would like to run automated tests via JUnit for example.<\/p>\n<p>Fortunately, the function invoker is an open source project from Google and yours truly has proposed a PR that allows the use it via automated tests by proposing a <a href=\"https:\/\/github.com\/GoogleCloudPlatform\/functions-framework-java\/pull\/128\" title=\"Invoker.stop()\">stop method<\/a> that was missing.<\/p>\n<p>Using its latest version, we can add the invoker as a Maven dependency to our project to use it in a unit test<\/p>\n<pre>\n\n    com.google.cloud.functions.invoker\n    java-function-invoker\n    1.1.1\n    test\n\n<\/pre>\n<p>You can then create JUnit tests, for example, for our HTTP function <code>HelloHttpFunction<\/code> we will have the following test:<\/p>\n<pre>\nclass HttpFunctionTestCase {\n    @Test\n    public void test() throws Exception {\n        \/\/ start the invoker without joining to avoid blocking the thread\n        Invoker invoker = new Invoker(\n                8081,\n                \"org.example.HelloHttpFunction\",\n                \"http\",\n                Thread.currentThread().getContextClassLoader());\n        invoker.startTestServer();\n\n        \/\/ test the function using REST-assured\n        when()\n                .get(\"http:\/\/localhost:8081\")\n                .then()\n                .statusCode(200)\n                .body(is(\"Hello World!\"));\n\n        \/\/ stop the invoker\n        invoker.stopServer();\n    }\n}\n<\/pre>\n<p><em>The <a href=\"https:\/\/rest-assured.io\/\" title=\"REST-assured website\">REST-assured<\/a> framework is used here to make writing HTTP tests easier.<\/em><\/p>\n<p>The third parameter to pass when instantiating the invoker is the type of function to test, all function types are supported:<\/p>\n<ul><li><strong>http<\/strong>: for HTTP functions;<\/li>\n\n<li><strong>event<\/strong>: for backgound functions;<\/li>\n\n<li><strong>cloudevent<\/strong>: for Cloud Events functions.<\/li>\n<\/ul>\n<p>To test a background function that reacts to a Cloud Storage event, we&#8217;re going to send a JSON-formatted event via a HTTP POST to the invoker URL. We can use REST-assured for this as we did for an HTTP function.<\/p>\n<pre>\nclass BackgroundStorageFunctionTestCase {\n    @Test\n    public void test() throws Exception {\n        \/\/ start the invoker without joining to avoid blocking the thread\n        Invoker invoker = new Invoker(\n                8081,\n                \"org.example.BackgroundStorageFunction\",\n                \"event\",\n                Thread.currentThread().getContextClassLoader());\n        invoker.startTestServer();\n\n        \/\/ test the function using REST-assured\n        given()\n                .body(\"{\\\"data\\\":{\\\"name\\\":\\\"hello.txt\\\"}}\")\n                .when()\n                .post(\"http:\/\/localhost:8081\")\n                .then()\n                .statusCode(200);\n\n        \/\/ stop the invoker\n        invoker.stopServer();\n    }\n<\/pre>\n<p>In conclusion, thanks to version 1.1.1 of the Goole Cloud function invoker, we can test our functions automatically with JUnit5, and ensure their quality and functional non-regression in a CI workflow.<\/p>","protected":false},"excerpt":{"rendered":"<p>Until recently, testing a Google Cloud Function written in Java could be done via the invoker provided by the Google Cloud Functions SDK but not via a unit test. But this changed recently! Let&#8217;s take the following HTTP function as an example: public class HelloHttpFunction implements HttpFunction { @Override public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception { Writer writer = httpResponse.getWriter(); writer.write(&#8220;Hello World&#8221;); } } After packaging the function into an \u00fcber JAR, we can download the Google Cloud&#8230;<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/tester-une-java-google-cloud-function\/\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[9],"tags":[],"class_list":["post-1532","post","type-post","status-publish","format-standard","hentry","category-informatique"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1560,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/quarkus-tip-tester-une-fonction-google-cloud\/","url_meta":{"origin":1532,"position":0},"title":"Quarkus Tip: Testing a Google Cloud function","author":"admin","date":"Thursday December 29th, 2022","format":false,"excerpt":"I recently contributed a PR to Quarkus that contains a testing framework for Google Cloud functions. Quarkus supports creating Google Cloud functions three different ways: Using the Google Cloud API. Using a Quarkus HTTP extension: RESTEasy, Reactive routes, Servlet, Spring Web. Using Funqy, the cloud provider agnostic Quarkus function API.\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1345,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/quarkus-et-les-google-cloud-functions\/","url_meta":{"origin":1532,"position":1},"title":"Quarkus and  the Google Cloud Functions","author":"admin","date":"Tuesday November  2nd, 2021","format":false,"excerpt":"Quarkus is a microservice framework designed for the cloud and the containers. It is designed to have a reduced memory usage and the shortest possible startup time. It is mainly based on standards (Jakarta EE, Eclipse MicroProfile, ...) and allows the use of mature and widespread Java libraries via its\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1068,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/j-ai-teste-java-google-cloud-functions-aplha\/","url_meta":{"origin":1532,"position":2},"title":"(Fran\u00e7ais) J&#8217;ai test\u00e9 Java Google Cloud Functions Alpha","author":"admin","date":"Wednesday May  6th, 2020","format":false,"excerpt":"Sorry, this entry is only available in Fran\u00e7ais.","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1440,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/google-cloud-functions-2nd-gen\/","url_meta":{"origin":1532,"position":3},"title":"Google Cloud Functions 2nd gen","author":"admin","date":"Tuesday March 29th, 2022","format":false,"excerpt":"Sorry, this entry is only available in Fran\u00e7ais.","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/cloud-function-gen2-instances.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/cloud-function-gen2-instances.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/cloud-function-gen2-instances.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":2089,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/deploy-a-quarkus-application-in-cloud-run\/","url_meta":{"origin":1532,"position":4},"title":"Deploy a Quarkus application in Cloud Run","author":"admin","date":"Tuesday December 30th, 2025","format":false,"excerpt":"Quarkus is a microservice development framework designed for the cloud and containers. It is designed to have reduced memory usage and the shortest possible startup time. It is mainly based on standards (Jakarta EE, Eclipse MicroProfile, etc.) and allows the use of mature and widely used Java libraries via its\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":377,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/session-chti-jug-sur-les-technologies-google\/","url_meta":{"origin":1532,"position":5},"title":"Ch&#8217;ti Jug: les technologies Google","author":"admin","date":"Wednesday November 11th, 2009","format":false,"excerpt":"Hello, Lundi j'ai \u00e9t\u00e9 \u00e0 la session du Ch'ti Jug sur les technologies Google qui s'est pass\u00e9 \u00e0 l'ISEN et \u00e9tait sponsoris\u00e9e par SII. C'\u00e9tait la premi\u00e8re fois que j'assistais \u00e0 un \u00e9v\u00e8nement organis\u00e9 par le Ch'ti Jug et comme c'\u00e9tait int\u00e9ressant, j'aimerais partager avec vous l\u00e0 dessus. Ch'ti Jug?\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"Google Wave","src":"https:\/\/i0.wp.com\/loicmathieu.free.fr\/wordpress\/wp-content\/uploads\/google-wave.jpg?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/loicmathieu.free.fr\/wordpress\/wp-content\/uploads\/google-wave.jpg?resize=350%2C200 1x, https:\/\/i0.wp.com\/loicmathieu.free.fr\/wordpress\/wp-content\/uploads\/google-wave.jpg?resize=525%2C300 1.5x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/1532","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/comments?post=1532"}],"version-history":[{"count":10,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/1532\/revisions"}],"predecessor-version":[{"id":1542,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/1532\/revisions\/1542"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/media?parent=1532"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/categories?post=1532"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/tags?post=1532"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}