{"action":"created","comment":{"url":"https://api.github.com/repos/OpenLiberty/blogs/pulls/comments/267961117","pull_request_review_id":217494373,"id":267961117,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI2Nzk2MTExNw==","diff_hunk":"@@ -0,0 +1,317 @@\n+---\n+layout: post\n+title:  \"Easy integration testing for JavaEE and MicroProfile applications with Testcontainers\"\n+date:   2019-03-16 07:45:00 -0000\n+categories: blog\n+author_picture: https://avatars2.githubusercontent.com/u/5427967\n+author_github: https://github.com/aguibert\n+seo-title: Easy integration testing for JavaEE and MicroProfile applications with Testcontainers\n+seo-description: Learn how to write simple and effective integration tests that run against your real application's docker container. No mock objects needed. \n+blog_description: \"Learn how to write simple and effective integration tests that run against your real application's docker container. No mock objects needed.\"\n+---\n+:description: Learn how to write simple and effective integration tests that test your real application as it would run in production\n+=  Easy integration testing for JavaEE and MicroProfile applications with Testcontainers\n+Andy Guibert <https://github.com/aguibert>\n+\n+Have you ever toiled with creating mock objects for unit tests? How about custom setup steps for integration tests? Ever had an issue in production because of differences in behavior between testing and production environments?\n+\n+If you answered yes to any of these questions, answer one more for me: do your applications run in docker containers?\n+\n+One of the great benefits of docker is that we get a nice consistent package that contains everything down to the OS, meaning it's portable to any hardware. Great, so lets leverage this to get consistent testing environments too!\n+\n+== Introducing Testcontainers\n+\n+image::https://d33wubrfki0l68.cloudfront.net/a661dbbe55be3e9cb77889f24835a44c6daf53c2/ce0aa/logo.png[Testcontainers logo, align=\"center\"]\n+\n+https://www.testcontainers.org/[Testcontainers] is a great open source library that essentially wraps Docker in a Java API, and has first-class integration with JUnit. It is mainly used for external resource dependencies, and has first-class support for many popular databases such as Postgres and MySQL. In addition, it also has generic support for any docker container.\n+\n+Using the `GenericContainer` API, we can get a running Liberty server in no time!\n+\n+==== Gradle dependencies\n+[source,groovy]\n+----\n+dependencies {\n+  testCompile group: 'junit', name: 'junit', version: '4.12'\n+  testCompile group: 'org.testcontainers', name: 'testcontainers', version: '1.10.6'\n+}\n+----\n+\n+==== JUnit test class\n+[source,java]\n+----\n+import org.testcontainers.containers.GenericContainer;\n+\n+public class SampleTest {\n+\n+    @ClassRule\n+    public static GenericContainer libertyContainer = new GenericContainer(\"open-liberty:microProfile2\")\n+                    .withExposedPorts(9080)\n+                    .waitingFor(Wait.forHttp(\"/\"));\n+\n+}\n+----\n+\n+To break this down a bit:\n+\n+* JUnit's `@ClassRule` on any Testcontainer container object will result in the container being started before any `@Test` methods run, and then stopped after all tests are done running.\n+* We need to declare what ports to expose from the container -- in this case 9080, as that is Liberty's default HTTP port\n+* Using `waitFor()` we declare the criteria for the container being \"ready\". This check must pass before any tests start running. There are a few approaches to wait stratigies, which are https://www.testcontainers.org/features/startup_and_waits/[outlined in more detail in the Testcontainers documentation].\n+\n+== Testing my application's container\n+\n+Being able to start a Liberty container easily from a JUnit test is ok, but we need to get our test application in the container too. Since I am already putting my application in a Docker container, I have this Docker file on-hand already (it's the same one I use for production)","path":"drafts/2019-03-15-integration-testing-with-testcontainers.adoc","position":62,"original_position":62,"commit_id":"874bc163353ad1b340ec9b190456160b1a2a110e","original_commit_id":"874bc163353ad1b340ec9b190456160b1a2a110e","user":{"login":"kwsutter","id":7726127,"node_id":"MDQ6VXNlcjc3MjYxMjc=","avatar_url":"https://avatars3.githubusercontent.com/u/7726127?v=4","gravatar_id":"","url":"https://api.github.com/users/kwsutter","html_url":"https://github.com/kwsutter","followers_url":"https://api.github.com/users/kwsutter/followers","following_url":"https://api.github.com/users/kwsutter/following{/other_user}","gists_url":"https://api.github.com/users/kwsutter/gists{/gist_id}","starred_url":"https://api.github.com/users/kwsutter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kwsutter/subscriptions","organizations_url":"https://api.github.com/users/kwsutter/orgs","repos_url":"https://api.github.com/users/kwsutter/repos","events_url":"https://api.github.com/users/kwsutter/events{/privacy}","received_events_url":"https://api.github.com/users/kwsutter/received_events","type":"User","site_admin":false},"body":"Having this application already packaged for a docker container is key to this whole exercise, right?  So, if I'm new to this and I currently don't have this packaging in place, where can I look?  Will you have a github repo with this sample code so that I don't have invent something if I'm still in education mode?","created_at":"2019-03-21T21:19:21Z","updated_at":"2019-03-21T21:33:06Z","html_url":"https://github.com/OpenLiberty/blogs/pull/39#discussion_r267961117","pull_request_url":"https://api.github.com/repos/OpenLiberty/blogs/pulls/39","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/OpenLiberty/blogs/pulls/comments/267961117"},"html":{"href":"https://github.com/OpenLiberty/blogs/pull/39#discussion_r267961117"},"pull_request":{"href":"https://api.github.com/repos/OpenLiberty/blogs/pulls/39"}}},"pull_request":{"url":"https://api.github.com/repos/OpenLiberty/blogs/pulls/39","id":262137431,"node_id":"MDExOlB1bGxSZXF1ZXN0MjYyMTM3NDMx","html_url":"https://github.com/OpenLiberty/blogs/pull/39","diff_url":"https://github.com/OpenLiberty/blogs/pull/39.diff","patch_url":"https://github.com/OpenLiberty/blogs/pull/39.patch","issue_url":"https://api.github.com/repos/OpenLiberty/blogs/issues/39","number":39,"state":"open","locked":false,"title":"Testcontainers integration testing blog post","user":{"login":"aguibert","id":5427967,"node_id":"MDQ6VXNlcjU0Mjc5Njc=","avatar_url":"https://avatars2.githubusercontent.com/u/5427967?v=4","gravatar_id":"","url":"https://api.github.com/users/aguibert","html_url":"https://github.com/aguibert","followers_url":"https://api.github.com/users/aguibert/followers","following_url":"https://api.github.com/users/aguibert/following{/other_user}","gists_url":"https://api.github.com/users/aguibert/gists{/gist_id}","starred_url":"https://api.github.com/users/aguibert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aguibert/subscriptions","organizations_url":"https://api.github.com/users/aguibert/orgs","repos_url":"https://api.github.com/users/aguibert/repos","events_url":"https://api.github.com/users/aguibert/events{/privacy}","received_events_url":"https://api.github.com/users/aguibert/received_events","type":"User","site_admin":false},"body":"","created_at":"2019-03-18T16:41:14Z","updated_at":"2019-03-21T21:33:06Z","closed_at":null,"merged_at":null,"merge_commit_sha":"13536120166e885678d3590fbf263acb73872e12","assignee":{"login":"aguibert","id":5427967,"node_id":"MDQ6VXNlcjU0Mjc5Njc=","avatar_url":"https://avatars2.githubusercontent.com/u/5427967?v=4","gravatar_id":"","url":"https://api.github.com/users/aguibert","html_url":"https://github.com/aguibert","followers_url":"https://api.github.com/users/aguibert/followers","following_url":"https://api.github.com/users/aguibert/following{/other_user}","gists_url":"https://api.github.com/users/aguibert/gists{/gist_id}","starred_url":"https://api.github.com/users/aguibert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aguibert/subscriptions","organizations_url":"https://api.github.com/users/aguibert/orgs","repos_url":"https://api.github.com/users/aguibert/repos","events_url":"https://api.github.com/users/aguibert/events{/privacy}","received_events_url":"https://api.github.com/users/aguibert/received_events","type":"User","site_admin":false},"assignees":[{"login":"aguibert","id":5427967,"node_id":"MDQ6VXNlcjU0Mjc5Njc=","avatar_url":"https://avatars2.githubusercontent.com/u/5427967?v=4","gravatar_id":"","url":"https://api.github.com/users/aguibert","html_url":"https://github.com/aguibert","followers_url":"https://api.github.com/users/aguibert/followers","following_url":"https://api.github.com/users/aguibert/following{/other_user}","gists_url":"https://api.github.com/users/aguibert/gists{/gist_id}","starred_url":"https://api.github.com/users/aguibert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aguibert/subscriptions","organizations_url":"https://api.github.com/users/aguibert/orgs","repos_url":"https://api.github.com/users/aguibert/repos","events_url":"https://api.github.com/users/aguibert/events{/privacy}","received_events_url":"https://api.github.com/users/aguibert/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"lauracowen","id":3322532,"node_id":"MDQ6VXNlcjMzMjI1MzI=","avatar_url":"https://avatars3.githubusercontent.com/u/3322532?v=4","gravatar_id":"","url":"https://api.github.com/users/lauracowen","html_url":"https://github.com/lauracowen","followers_url":"https://api.github.com/users/lauracowen/followers","following_url":"https://api.github.com/users/lauracowen/following{/other_user}","gists_url":"https://api.github.com/users/lauracowen/gists{/gist_id}","starred_url":"https://api.github.com/users/lauracowen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lauracowen/subscriptions","organizations_url":"https://api.github.com/users/lauracowen/orgs","repos_url":"https://api.github.com/users/lauracowen/repos","events_url":"https://api.github.com/users/lauracowen/events{/privacy}","received_events_url":"https://api.github.com/users/lauracowen/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/OpenLiberty/blogs/pulls/39/commits","review_comments_url":"https://api.github.com/repos/OpenLiberty/blogs/pulls/39/comments","review_comment_url":"https://api.github.com/repos/OpenLiberty/blogs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/OpenLiberty/blogs/issues/39/comments","statuses_url":"https://api.github.com/repos/OpenLiberty/blogs/statuses/874bc163353ad1b340ec9b190456160b1a2a110e","head":{"label":"aguibert:testcontainers-integration-testing","ref":"testcontainers-integration-testing","sha":"874bc163353ad1b340ec9b190456160b1a2a110e","user":{"login":"aguibert","id":5427967,"node_id":"MDQ6VXNlcjU0Mjc5Njc=","avatar_url":"https://avatars2.githubusercontent.com/u/5427967?v=4","gravatar_id":"","url":"https://api.github.com/users/aguibert","html_url":"https://github.com/aguibert","followers_url":"https://api.github.com/users/aguibert/followers","following_url":"https://api.github.com/users/aguibert/following{/other_user}","gists_url":"https://api.github.com/users/aguibert/gists{/gist_id}","starred_url":"https://api.github.com/users/aguibert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aguibert/subscriptions","organizations_url":"https://api.github.com/users/aguibert/orgs","repos_url":"https://api.github.com/users/aguibert/repos","events_url":"https://api.github.com/users/aguibert/events{/privacy}","received_events_url":"https://api.github.com/users/aguibert/received_events","type":"User","site_admin":false},"repo":{"id":163205233,"node_id":"MDEwOlJlcG9zaXRvcnkxNjMyMDUyMzM=","name":"blogs","full_name":"aguibert/blogs","private":false,"owner":{"login":"aguibert","id":5427967,"node_id":"MDQ6VXNlcjU0Mjc5Njc=","avatar_url":"https://avatars2.githubusercontent.com/u/5427967?v=4","gravatar_id":"","url":"https://api.github.com/users/aguibert","html_url":"https://github.com/aguibert","followers_url":"https://api.github.com/users/aguibert/followers","following_url":"https://api.github.com/users/aguibert/following{/other_user}","gists_url":"https://api.github.com/users/aguibert/gists{/gist_id}","starred_url":"https://api.github.com/users/aguibert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aguibert/subscriptions","organizations_url":"https://api.github.com/users/aguibert/orgs","repos_url":"https://api.github.com/users/aguibert/repos","events_url":"https://api.github.com/users/aguibert/events{/privacy}","received_events_url":"https://api.github.com/users/aguibert/received_events","type":"User","site_admin":false},"html_url":"https://github.com/aguibert/blogs","description":"Blog posts for https://openliberty.io","fork":true,"url":"https://api.github.com/repos/aguibert/blogs","forks_url":"https://api.github.com/repos/aguibert/blogs/forks","keys_url":"https://api.github.com/repos/aguibert/blogs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aguibert/blogs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aguibert/blogs/teams","hooks_url":"https://api.github.com/repos/aguibert/blogs/hooks","issue_events_url":"https://api.github.com/repos/aguibert/blogs/issues/events{/number}","events_url":"https://api.github.com/repos/aguibert/blogs/events","assignees_url":"https://api.github.com/repos/aguibert/blogs/assignees{/user}","branches_url":"https://api.github.com/repos/aguibert/blogs/branches{/branch}","tags_url":"https://api.github.com/repos/aguibert/blogs/tags","blobs_url":"https://api.github.com/repos/aguibert/blogs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aguibert/blogs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aguibert/blogs/git/refs{/sha}","trees_url":"https://api.github.com/repos/aguibert/blogs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aguibert/blogs/statuses/{sha}","languages_url":"https://api.github.com/repos/aguibert/blogs/languages","stargazers_url":"https://api.github.com/repos/aguibert/blogs/stargazers","contributors_url":"https://api.github.com/repos/aguibert/blogs/contributors","subscribers_url":"https://api.github.com/repos/aguibert/blogs/subscribers","subscription_url":"https://api.github.com/repos/aguibert/blogs/subscription","commits_url":"https://api.github.com/repos/aguibert/blogs/commits{/sha}","git_commits_url":"https://api.github.com/repos/aguibert/blogs/git/commits{/sha}","comments_url":"https://api.github.com/repos/aguibert/blogs/comments{/number}","issue_comment_url":"https://api.github.com/repos/aguibert/blogs/issues/comments{/number}","contents_url":"https://api.github.com/repos/aguibert/blogs/contents/{+path}","compare_url":"https://api.github.com/repos/aguibert/blogs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aguibert/blogs/merges","archive_url":"https://api.github.com/repos/aguibert/blogs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aguibert/blogs/downloads","issues_url":"https://api.github.com/repos/aguibert/blogs/issues{/number}","pulls_url":"https://api.github.com/repos/aguibert/blogs/pulls{/number}","milestones_url":"https://api.github.com/repos/aguibert/blogs/milestones{/number}","notifications_url":"https://api.github.com/repos/aguibert/blogs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aguibert/blogs/labels{/name}","releases_url":"https://api.github.com/repos/aguibert/blogs/releases{/id}","deployments_url":"https://api.github.com/repos/aguibert/blogs/deployments","created_at":"2018-12-26T18:04:33Z","updated_at":"2019-03-15T20:49:08Z","pushed_at":"2019-03-18T18:46:27Z","git_url":"git://github.com/aguibert/blogs.git","ssh_url":"git@github.com:aguibert/blogs.git","clone_url":"https://github.com/aguibert/blogs.git","svn_url":"https://github.com/aguibert/blogs","homepage":"https://openliberty.io/blog/","size":3540,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"OpenLiberty:master","ref":"master","sha":"95398d6c566eeebc5f06bc655b4179940e464558","user":{"login":"OpenLiberty","id":28316667,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4MzE2NjY3","avatar_url":"https://avatars2.githubusercontent.com/u/28316667?v=4","gravatar_id":"","url":"https://api.github.com/users/OpenLiberty","html_url":"https://github.com/OpenLiberty","followers_url":"https://api.github.com/users/OpenLiberty/followers","following_url":"https://api.github.com/users/OpenLiberty/following{/other_user}","gists_url":"https://api.github.com/users/OpenLiberty/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenLiberty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenLiberty/subscriptions","organizations_url":"https://api.github.com/users/OpenLiberty/orgs","repos_url":"https://api.github.com/users/OpenLiberty/repos","events_url":"https://api.github.com/users/OpenLiberty/events{/privacy}","received_events_url":"https://api.github.com/users/OpenLiberty/received_events","type":"Organization","site_admin":false},"repo":{"id":147538901,"node_id":"MDEwOlJlcG9zaXRvcnkxNDc1Mzg5MDE=","name":"blogs","full_name":"OpenLiberty/blogs","private":false,"owner":{"login":"OpenLiberty","id":28316667,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4MzE2NjY3","avatar_url":"https://avatars2.githubusercontent.com/u/28316667?v=4","gravatar_id":"","url":"https://api.github.com/users/OpenLiberty","html_url":"https://github.com/OpenLiberty","followers_url":"https://api.github.com/users/OpenLiberty/followers","following_url":"https://api.github.com/users/OpenLiberty/following{/other_user}","gists_url":"https://api.github.com/users/OpenLiberty/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenLiberty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenLiberty/subscriptions","organizations_url":"https://api.github.com/users/OpenLiberty/orgs","repos_url":"https://api.github.com/users/OpenLiberty/repos","events_url":"https://api.github.com/users/OpenLiberty/events{/privacy}","received_events_url":"https://api.github.com/users/OpenLiberty/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/OpenLiberty/blogs","description":"Blog posts for https://openliberty.io","fork":false,"url":"https://api.github.com/repos/OpenLiberty/blogs","forks_url":"https://api.github.com/repos/OpenLiberty/blogs/forks","keys_url":"https://api.github.com/repos/OpenLiberty/blogs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/OpenLiberty/blogs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/OpenLiberty/blogs/teams","hooks_url":"https://api.github.com/repos/OpenLiberty/blogs/hooks","issue_events_url":"https://api.github.com/repos/OpenLiberty/blogs/issues/events{/number}","events_url":"https://api.github.com/repos/OpenLiberty/blogs/events","assignees_url":"https://api.github.com/repos/OpenLiberty/blogs/assignees{/user}","branches_url":"https://api.github.com/repos/OpenLiberty/blogs/branches{/branch}","tags_url":"https://api.github.com/repos/OpenLiberty/blogs/tags","blobs_url":"https://api.github.com/repos/OpenLiberty/blogs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/OpenLiberty/blogs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/OpenLiberty/blogs/git/refs{/sha}","trees_url":"https://api.github.com/repos/OpenLiberty/blogs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/OpenLiberty/blogs/statuses/{sha}","languages_url":"https://api.github.com/repos/OpenLiberty/blogs/languages","stargazers_url":"https://api.github.com/repos/OpenLiberty/blogs/stargazers","contributors_url":"https://api.github.com/repos/OpenLiberty/blogs/contributors","subscribers_url":"https://api.github.com/repos/OpenLiberty/blogs/subscribers","subscription_url":"https://api.github.com/repos/OpenLiberty/blogs/subscription","commits_url":"https://api.github.com/repos/OpenLiberty/blogs/commits{/sha}","git_commits_url":"https://api.github.com/repos/OpenLiberty/blogs/git/commits{/sha}","comments_url":"https://api.github.com/repos/OpenLiberty/blogs/comments{/number}","issue_comment_url":"https://api.github.com/repos/OpenLiberty/blogs/issues/comments{/number}","contents_url":"https://api.github.com/repos/OpenLiberty/blogs/contents/{+path}","compare_url":"https://api.github.com/repos/OpenLiberty/blogs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/OpenLiberty/blogs/merges","archive_url":"https://api.github.com/repos/OpenLiberty/blogs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/OpenLiberty/blogs/downloads","issues_url":"https://api.github.com/repos/OpenLiberty/blogs/issues{/number}","pulls_url":"https://api.github.com/repos/OpenLiberty/blogs/pulls{/number}","milestones_url":"https://api.github.com/repos/OpenLiberty/blogs/milestones{/number}","notifications_url":"https://api.github.com/repos/OpenLiberty/blogs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/OpenLiberty/blogs/labels{/name}","releases_url":"https://api.github.com/repos/OpenLiberty/blogs/releases{/id}","deployments_url":"https://api.github.com/repos/OpenLiberty/blogs/deployments","created_at":"2018-09-05T15:20:19Z","updated_at":"2019-03-13T17:23:31Z","pushed_at":"2019-03-21T14:39:32Z","git_url":"git://github.com/OpenLiberty/blogs.git","ssh_url":"git@github.com:OpenLiberty/blogs.git","clone_url":"https://github.com/OpenLiberty/blogs.git","svn_url":"https://github.com/OpenLiberty/blogs","homepage":"https://openliberty.io/blog/","size":3544,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":8,"mirror_url":null,"archived":false,"open_issues_count":8,"license":null,"forks":8,"open_issues":8,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/OpenLiberty/blogs/pulls/39"},"html":{"href":"https://github.com/OpenLiberty/blogs/pull/39"},"issue":{"href":"https://api.github.com/repos/OpenLiberty/blogs/issues/39"},"comments":{"href":"https://api.github.com/repos/OpenLiberty/blogs/issues/39/comments"},"review_comments":{"href":"https://api.github.com/repos/OpenLiberty/blogs/pulls/39/comments"},"review_comment":{"href":"https://api.github.com/repos/OpenLiberty/blogs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/OpenLiberty/blogs/pulls/39/commits"},"statuses":{"href":"https://api.github.com/repos/OpenLiberty/blogs/statuses/874bc163353ad1b340ec9b190456160b1a2a110e"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"kwsutter"}}