{"id":2271,"date":"2018-08-01T14:31:52","date_gmt":"2018-08-01T13:31:52","guid":{"rendered":"https:\/\/www.entropywins.wtf\/blog\/?p=2271"},"modified":"2019-02-23T06:18:48","modified_gmt":"2019-02-23T05:18:48","slug":"clean-architecture-usecase-tests","status":"publish","type":"post","link":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/","title":{"rendered":"Clean Architecture: UseCase tests"},"content":{"rendered":"<p>When creating an application that follows <a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\">The Clean Architecture<\/a> you end up with a number of UseCases that hold your application logic. In this blog post I outline a testing pattern for effectively testing these UseCases and avoiding common pitfalls.<\/p>\n<h2>Testing UseCases<\/h2>\n<p>A UseCase contains the application logic for a single &#8220;action&#8221; that your system supports. For instance &#8220;cancel a membership&#8221;. This application logic interacts with the domain and various services. These services and the domain should have their own unit and integration tests. Each UseCase gets used in one or more applications, where it gets invoked from inside the presentation layer. Typically you want to have a few integration or edge-to-edge tests that cover this invocation. In this post I look at how to test the application logic of the UseCase itself.<\/p>\n<p>UseCases tend to have &#8220;many&#8221; collaborators. I can&#8217;t recall any that had less than 3. For the typical UseCase the number is likely closer to 6 or 7, with more collaborators being possible even when the design is good. That means constructing a UseCase takes some work: you need to provide working instances of all the collaborators.<\/p>\n<h2>Integration Testing<\/h2>\n<p>One way to deal with this is to write integration tests for your UseCases. Simply get an instance of the UseCase from your Top Level Factory or Dependency Injection Container.<\/p>\n<p>This approach often requires you to mutate the factory or DIC. Want to test that an exception from the persistence service gets handled properly? You&#8217;ll need to use some <a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/05\/13\/5-ways-to-write-better-mocks\/\">test double<\/a> instead of the real service, or perhaps mutate the real service in some way. Want to verify a mail got send? Definitely want to use a <a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/05\/13\/5-ways-to-write-better-mocks\/\">Spy<\/a> here instead of the real service. Mutability comes with a cost so is better avoided.<\/p>\n<p>A second issue with using real collaborators is that your tests get slow due to real persistence usage. Even using an in-memory SQLite database (that needs initialization) instead of a simple in-memory fake repository makes for a speed difference of easily two orders of magnitude.<\/p>\n<h2>Unit Testing<\/h2>\n<p>While there might be some cases where integration tests make sense, normally it is better to write unit tests for UseCases. This means having test doubles for all collaborators. Which leads us to the question of how to best inject these test doubles into our UseCases.<\/p>\n<p>As example I will use the CancelMembershipApplicationUseCase of the <a href=\"https:\/\/wikimedia.de\/en\/\">Wikimedia Deutschland<\/a> <a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/rewriting-the-wikimedia-deutschland-funrdraising\/\">fundrasing application<\/a>.<\/p>\n<pre class=\"lang:php decode:true\">function __construct(ApplicationAuthorizer $authorizer, ApplicationRepository $repository, TemplateMailerInterface $mailer) {\n    $this-&gt;authorizer = $authorizer;\n    $this-&gt;repository = $repository;\n    $this-&gt;mailer = $mailer;\n}<\/pre>\n<p>This UseCase uses 3 collaborators. An authorization service, a repository (persistence service) and a mailing service. First it checks if the operation is allowed with the authorizer, then it interacts with the persistence and finally, if all went well, it uses the mailing service to send a confirmation email. Our unit test should test all this behavior and needs to inject test doubles for the 3 collaborators.<\/p>\n<p>The most obvious approach is to construct the UseCase in each test method.<\/p>\n<pre class=\"lang:php decode:true \">public function testGivenIdOfUnknownDonation_cancellationIsNotSuccessful(): void {\n    $useCase = new CancelMembershipApplicationUseCase(\n        new SucceedingAuthorizer(),\n        $this-&gt;newRepositoryWithCancellableDonation(),\n        new MailerSpy()\n    );\n\n    $response = $useCase-&gt;cancelApplication(\n        new CancellationRequest( self::ID_OF_NON_EXISTING_APPLICATION )\n    );\n\n    $this-&gt;assertFalse( $response-&gt;cancellationWasSuccessful() );\n}\n\npublic function testGivenIdOfCancellableApplication_cancellationIsSuccessful(): void {\n    $useCase = new CancelMembershipApplicationUseCase(\n        new SucceedingAuthorizer(),\n        $this-&gt;newRepositoryWithCancellableDonation(),\n        new MailerSpy()\n    );\n    \n    $response = $useCase-&gt;cancelApplication(\n        new CancellationRequest( $this-&gt;cancelableApplication-&gt;getId() )\n    );\n\n    $this-&gt;assertTrue( $response-&gt;cancellationWasSuccessful() );\n}<\/pre>\n<p>Note how both these test methods use the same test doubles. This is not always the case, for instance when testing authorization failure, the test double for the authorizer service will differ, and when testing persistence failure, the test double for the persistence service will differ.<\/p>\n<pre class=\"lang:php decode:true\">public function testWhenAuthorizationFails_cancellationFails(): void {\n    $useCase = new CancelMembershipApplicationUseCase(\n        new FailingAuthorizer(),\n        $this-&gt;newRepositoryWithCancellableDonation(),\n        new MailerSpy()\n    );\n\n    $response = $useCase-&gt;cancelApplication(\n        new CancellationRequest( $this-&gt;cancelableApplication-&gt;getId() )\n    );\n\n    $this-&gt;assertFalse( $response-&gt;cancellationWasSuccessful() );\n}<\/pre>\n<p>Normally a test function will only change a single test double.<\/p>\n<p>UseCases tend to have, on average, two or more behaviors (and thus tests) per collaborator. That means for most UseCases you will be repeating the construction of the UseCase in a dozen or more test functions. That is a problem. Ask yourself why.<\/p>\n<p>If the answer you came up with was DRY then think again and read my <a href=\"https:\/\/www.entropywins.wtf\/blog\/2017\/09\/06\/the-fallacy-of-dry\/\">blog post on DRY<\/a> \ud83d\ude09 The primary issue is that you couple each of those test methods to the list of collaborators. So when the constructor signature of your UseCase changes, you will need to do <a href=\"https:\/\/en.wikipedia.org\/wiki\/Shotgun_surgery\">Shotgun Surgery<\/a> and update all test functions. Even if those tests have nothing to do with the changed collaborator. A second issue is that you pollute the test methods with irrelevant details, making them harder to read.<\/p>\n<h2>Default Test Doubles Pattern<\/h2>\n<p><em>The pattern is demonstrated using PHP + PHPUnit and will need some adaptation when using a testing framework that does not work with a class based model like that of PHPUnit.<\/em><\/p>\n<p>The coupling to the constructor signature and resulting Shotgun Surgery can be avoided by having a default instance of the UseCase filled with the right test doubles. This can be done by having a newUseCase method that constructs the UseCase and returns it. A way to change specific collaborators is needed (ie a <code>FailingAuthorizer<\/code> to test\u00a0handling of failing authorization).<\/p>\n<pre class=\"lang:php decode:true\">private function newUseCase() {\n    return new CancelMembershipApplicationUseCase(\n        new SucceedingAuthorizer(),\n        new InMemoryApplicationRepository(),\n        new MailerSpy()\n    );\n}<\/pre>\n<p>Making the UseCase itself mutable is a big no-no. Adding optional parameters to the <code>newUseCase<\/code> method works in languages that have named parameters. Since <a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/02\/01\/missing-in-php7-named-parameters\/\">PHP does not have named parameters<\/a>, another solution is needed.<\/p>\n<p>An alternative approach to getting modified collaborators into the <code>newUseCase<\/code> method is using fields. This is less nice than named parameters, as it introduces mutable state on the level of the test class. Since in PHP this approach gives us named fields and is understandable by tools, it is better than either using a positional list of optional arguments or emulating named arguments with an associative array (key-value map).<\/p>\n<p>The fields can be set in the <code>setUp<\/code> method, which gets called by PHPUnit before the test methods. For each test method PHPUnit instantiates the test class, then calls <code>setUp<\/code>, and then calls the test method.<\/p>\n<pre class=\"lang:php decode:true\">public function setUp() {\n    $this-&gt;authorizer = new SucceedingAuthorizer();\n    $this-&gt;repository = new InMemoryApplicationRepository();\n    $this-&gt;mailer = new MailerSpy();\n\n    $this-&gt;cancelableApplication = ValidMembershipApplication::newDomainEntity();\n    $this-&gt;repository-&gt;storeApplication( $this-&gt;cancelableApplication );\n}<\/pre>\n<pre class=\"lang:php decode:true \">private function newUseCase(): CancelMembershipApplicationUseCase {\n    return new CancelMembershipApplicationUseCase(\n        $this-&gt;authorizer,\n        $this-&gt;repository,\n        $this-&gt;mailer\n    );\n}<\/pre>\n<p>With this field-based approach individual test methods can modify a specific collaborator by writing to the field before calling <code>newUseCase<\/code>.<\/p>\n<pre class=\"lang:php decode:true\">public function testWhenAuthorizationFails_cancellationFails(): void {\n    $this-&gt;authorizer = new FailingAuthorizer();\n\n    $response = $this-&gt;newUseCase()-&gt;cancelApplication(\n        new CancellationRequest( $this-&gt;cancelableApplication-&gt;getId() )\n    );\n\n    $this-&gt;assertFalse( $response-&gt;cancellationWasSuccessful() );\n}\n\npublic function testWhenSaveFails_cancellationFails() {\n    $this-&gt;repository-&gt;throwOnWrite();\n\n    $response = $this-&gt;newUseCase()-&gt;cancelApplication(\n        new CancellationRequest( $this-&gt;cancelableApplication-&gt;getId() )\n    );\n\n    $this-&gt;assertFalse( $response-&gt;cancellationWasSuccessful() );\n}<\/pre>\n<p>The choice of default collaborators is important. To minimize binding in the test functions, the <strong>default collaborators should not cause any failures<\/strong>. This is the case both when using the field-based approach and when using optional named parameters.<\/p>\n<p>If the authorization service failed by default, most test methods would need to modify it, even if they have nothing to do with authorization. And it is not always self-evident they need to modify the unrelated collaborator. Imagine the default authorization service indeed fails and that the <code>testWhenSaveFails_cancellationFails<\/code> test method forgets to modify it. This test method would end up passing even if the behavior it tests is broken, since the UseCase will return the expected failure result even before getting to the point where it saves something.<\/p>\n<p>This is why inside of the <code>setUp<\/code> function the example creates a &#8220;cancellable application&#8221; and puts it inside an in-memory test double of the repository.<\/p>\n<p>I chose the CancelMembershipApplication UseCase as an example because it is short and easy to understand. For most UseCases it is even more important to avoid the constructor signature coupling as this issue becomes more severe with size. And no matter how big or small the UseCase is, you benefit from not polluting your tests with unrelated setup details.<\/p>\n<p>You can view the whole <a href=\"https:\/\/github.com\/wmde\/fundraising-memberships\/blob\/e2b9f2cf4f3505ef2d4e5907045e108ec35f927e\/src\/UseCases\/CancelMembershipApplication\/CancelMembershipApplicationUseCase.php#L18\">CancelMembershipApplicationUseCase<\/a> and <a href=\"https:\/\/github.com\/wmde\/fundraising-memberships\/blob\/9eeddb14c55583c690f9896e4fb90d8ffdd84ca0\/tests\/Integration\/UseCases\/CancelMembershipApplication\/CancelMembershipApplicationUseCaseTest.php#L27\">CancelMembershipApplicationUseCaseTest<\/a>.<\/p>\n<h2>See also<\/h2>\n<script>(function() {\n\twindow.mc4wp = window.mc4wp || {\n\t\tlisteners: [],\n\t\tforms: {\n\t\t\ton: function(evt, cb) {\n\t\t\t\twindow.mc4wp.listeners.push(\n\t\t\t\t\t{\n\t\t\t\t\t\tevent   : evt,\n\t\t\t\t\t\tcallback: cb\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n})();\n<\/script><!-- Mailchimp for WordPress v4.12.1 - https:\/\/wordpress.org\/plugins\/mailchimp-for-wp\/ --><form id=\"mc4wp-form-1\" class=\"mc4wp-form mc4wp-form-2484\" method=\"post\" data-id=\"2484\" data-name=\"Implementing the Clean Architecture\" ><div class=\"mc4wp-form-fields\">Sign up below to receive news on my upcoming Clean Architecture book, including a discount:\r\n<div id=\"mc_embed_signup\">\r\n<div id=\"mc_embed_signup_scroll\">\r\n<div class=\"mc-field-group\"><input id=\"mce-EMAIL\" class=\"required email\" name=\"EMAIL\" type=\"email\" value=\"\" placeholder=\"Your email address\" \/><\/div>\r\n<div id=\"mce-responses\" class=\"clear\">\r\n<div id=\"mce-error-response\" class=\"response\" style=\"display: none;\"><\/div>\r\n<div id=\"mce-success-response\" class=\"response\" style=\"display: none;\"><\/div>\r\n<\/div>\r\n<div style=\"position: absolute; left: -5000px;\" aria-hidden=\"true\"><input tabindex=\"-1\" name=\"b_5e9453f7bede9f5b0220b2c42_9df25d9e9d\" type=\"text\" value=\"\" \/><\/div>\r\n<div class=\"clear\"><input id=\"mc-embedded-subscribe\" class=\"button\" name=\"subscribe\" type=\"submit\" value=\"Subscribe\" \/><\/div>\r\n<\/div>\r\n<\/div><\/div><label style=\"display: none !important;\">Leave this field empty if you're human: <input type=\"text\" name=\"_mc4wp_honeypot\" value=\"\" tabindex=\"-1\" autocomplete=\"off\" \/><\/label><input type=\"hidden\" name=\"_mc4wp_timestamp\" value=\"1779692968\" \/><input type=\"hidden\" name=\"_mc4wp_form_id\" value=\"2484\" \/><input type=\"hidden\" name=\"_mc4wp_form_element_id\" value=\"mc4wp-form-1\" \/><div class=\"mc4wp-response\"><\/div><\/form><!-- \/ Mailchimp for WordPress Plugin -->\n<ul>\n<li><a href=\"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/14\/clean-architecture-bounded-contexts\/\">Clean Architecture + Bounded Contexts<\/a><\/li>\n<li><a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\">Implementing the Clean Architecture<\/a><\/li>\n<li><a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/05\/13\/5-ways-to-write-better-mocks\/\">5 Ways to Write Better Mocks<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>When creating an application that follows The Clean Architecture you end up with a number of UseCases that hold your&hellip;<\/p>\n","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,"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":[7],"tags":[429,328,442,373,416,414,195,196,197,316,413,257,458],"class_list":["post-2271","post","type-post","status-publish","format-standard","hentry","category-programming","tag-clean-architecture","tag-clean-code","tag-coupling","tag-design-patterns","tag-maintainability","tag-mocks","tag-php","tag-phpunit","tag-planet-wikimedia","tag-software-design","tag-test-doubles","tag-testing","tag-unit-testing"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Clean Architecture: UseCase tests - Blog of Jeroen De Dauw<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Clean Architecture: UseCase tests - Blog of Jeroen De Dauw\" \/>\n<meta property=\"og:description\" content=\"When creating an application that follows The Clean Architecture you end up with a number of UseCases that hold your&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog of Jeroen De Dauw\" \/>\n<meta property=\"article:published_time\" content=\"2018-08-01T13:31:52+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-02-23T05:18:48+00:00\" \/>\n<meta name=\"author\" content=\"Jeroen\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/JeroenDeDauw\" \/>\n<meta name=\"twitter:site\" content=\"@JeroenDeDauw\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeroen\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2018\\\/08\\\/01\\\/clean-architecture-usecase-tests\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2018\\\/08\\\/01\\\/clean-architecture-usecase-tests\\\/\"},\"author\":{\"name\":\"Jeroen\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/#\\\/schema\\\/person\\\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"headline\":\"Clean Architecture: UseCase tests\",\"datePublished\":\"2018-08-01T13:31:52+00:00\",\"dateModified\":\"2019-02-23T05:18:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2018\\\/08\\\/01\\\/clean-architecture-usecase-tests\\\/\"},\"wordCount\":1151,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/#\\\/schema\\\/person\\\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"keywords\":[\"Clean Architecture\",\"Clean Code\",\"Coupling\",\"Design patterns\",\"Maintainability\",\"Mocks\",\"PHP\",\"PHPUnit\",\"Planet Wikimedia\",\"Software design\",\"Test Doubles\",\"Testing\",\"Unit testing\"],\"articleSection\":[\"Programming\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2018\\\/08\\\/01\\\/clean-architecture-usecase-tests\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2018\\\/08\\\/01\\\/clean-architecture-usecase-tests\\\/\",\"url\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2018\\\/08\\\/01\\\/clean-architecture-usecase-tests\\\/\",\"name\":\"Clean Architecture: UseCase tests - Blog of Jeroen De Dauw\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/#website\"},\"datePublished\":\"2018-08-01T13:31:52+00:00\",\"dateModified\":\"2019-02-23T05:18:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2018\\\/08\\\/01\\\/clean-architecture-usecase-tests\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2018\\\/08\\\/01\\\/clean-architecture-usecase-tests\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2018\\\/08\\\/01\\\/clean-architecture-usecase-tests\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Clean Architecture: UseCase tests\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/\",\"name\":\"Entropy Wins\",\"description\":\"A blog on Software Architecture, Design and Craftsmanship\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/#\\\/schema\\\/person\\\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/#\\\/schema\\\/person\\\/4e2ef14f2ca7dc3a0ac137d1692b66b7\",\"name\":\"Jeroen\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\",\"caption\":\"Jeroen\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\"},\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/jeroendedauw\\\/\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/JeroenDeDauw\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Clean Architecture: UseCase tests - Blog of Jeroen De Dauw","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/","og_locale":"en_US","og_type":"article","og_title":"Clean Architecture: UseCase tests - Blog of Jeroen De Dauw","og_description":"When creating an application that follows The Clean Architecture you end up with a number of UseCases that hold your&hellip;","og_url":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/","og_site_name":"Blog of Jeroen De Dauw","article_published_time":"2018-08-01T13:31:52+00:00","article_modified_time":"2019-02-23T05:18:48+00:00","author":"Jeroen","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/JeroenDeDauw","twitter_site":"@JeroenDeDauw","twitter_misc":{"Written by":"Jeroen","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/#article","isPartOf":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/"},"author":{"name":"Jeroen","@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"headline":"Clean Architecture: UseCase tests","datePublished":"2018-08-01T13:31:52+00:00","dateModified":"2019-02-23T05:18:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/"},"wordCount":1151,"commentCount":1,"publisher":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"keywords":["Clean Architecture","Clean Code","Coupling","Design patterns","Maintainability","Mocks","PHP","PHPUnit","Planet Wikimedia","Software design","Test Doubles","Testing","Unit testing"],"articleSection":["Programming"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/","url":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/","name":"Clean Architecture: UseCase tests - Blog of Jeroen De Dauw","isPartOf":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#website"},"datePublished":"2018-08-01T13:31:52+00:00","dateModified":"2019-02-23T05:18:48+00:00","breadcrumb":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.entropywins.wtf\/blog\/"},{"@type":"ListItem","position":2,"name":"Clean Architecture: UseCase tests"}]},{"@type":"WebSite","@id":"https:\/\/www.entropywins.wtf\/blog\/#website","url":"https:\/\/www.entropywins.wtf\/blog\/","name":"Entropy Wins","description":"A blog on Software Architecture, Design and Craftsmanship","publisher":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.entropywins.wtf\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7","name":"Jeroen","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g","caption":"Jeroen"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g"},"sameAs":["https:\/\/www.linkedin.com\/in\/jeroendedauw\/","https:\/\/x.com\/https:\/\/twitter.com\/JeroenDeDauw"]}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p74TBF-AD","jetpack-related-posts":[{"id":1846,"url":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/","url_meta":{"origin":2271,"position":0},"title":"Implementing the Clean Architecture","author":"Jeroen","date":"2016-11-24","format":false,"excerpt":"Both Domain Driven Design and architectures such as the Clean Architecture and Hexagonal are often talked about. It's hard to go to a conference on software development and not run into one of these topics. However it can be challenging to find good real-world examples. In this blog post I'll\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":2219,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/05\/09\/guidelines-for-new-software-projects\/","url_meta":{"origin":2271,"position":1},"title":"Guidelines for New Software Projects","author":"Jeroen","date":"2018-05-09","format":false,"excerpt":"In this blog post I share the Guidelines for New Software Projects that we use at Wikimedia Deutschland. I wrote down these guidelines recently after a third-party that was contracted by Wikimedia Deutschland delivered software that was problematic in several ways. The department contracting this third-party was not the software\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2210,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/14\/clean-architecture-bounded-contexts\/","url_meta":{"origin":2271,"position":2},"title":"Clean Architecture + Bounded Contexts","author":"Jeroen","date":"2018-08-14","format":false,"excerpt":"In this follow-up to Implementing the Clean Architecture I introduce you to a combination of The Clean Architecture and the strategic DDD pattern known as Bounded Contexts. At Wikimedia Deutschland we use this combination of The Clean Architecture and Bounded Contexts for our fundraising applications. In this post I describe\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":2278,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/14\/bounded-contexts-in-the-wikimedia-fundraising-software\/","url_meta":{"origin":2271,"position":3},"title":"Bounded Contexts in the Wikimedia Fundraising Software","author":"Jeroen","date":"2018-08-14","format":false,"excerpt":"In this follow-up to rewriting the Wikimedia Deutschland fundraising I tell the story of how we reorganized our codebases along the lines of the DDD strategic pattern Bounded Contexts. In 2016 the FUN team at Wikimedia Deutschland rewrote the Wikimedia Deutschland fundraising application. This new codebase uses The Clean Architecture\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"Diagram depicting Clean Architecture + Bounded Contexts","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":2495,"url":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/","url_meta":{"origin":2271,"position":4},"title":"Applications as Frameworks","author":"Jeroen","date":"2019-02-28","format":false,"excerpt":"What are the differences between building on top of a framework and building on top of an application? How does using an application as a framework cause problems, and how can these problems be avoided? That is what this post is all about. Decoupled web application In your typical web\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/grumpy-cat-no.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/grumpy-cat-no.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/grumpy-cat-no.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":2358,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/09\/09\/clean-architecture-bounded-contexts-diagram\/","url_meta":{"origin":2271,"position":5},"title":"Clean Architecture + Bounded Contexts diagram","author":"Jeroen","date":"2018-09-09","format":false,"excerpt":"I\u2019m happy to release a two Clean Architecture + Bounded Contexts diagrams into the public domain (CC0 1.0). I created these diagrams for Wikimedia Deutchland with the help of Jan Dittrich, Charlie Kritschmar and Hanna Petruschat. They represent the architecture of our fundraising codebase. I explain the rules of this\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=1050%2C600&ssl=1 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/2271","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/comments?post=2271"}],"version-history":[{"count":17,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/2271\/revisions"}],"predecessor-version":[{"id":2494,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/2271\/revisions\/2494"}],"wp:attachment":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/media?parent=2271"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/categories?post=2271"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/tags?post=2271"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}