{"id":294,"date":"2026-03-10T15:02:41","date_gmt":"2026-03-10T14:02:41","guid":{"rendered":"https:\/\/test.craftcode.be\/stubbing-in-python-met-dependency-injector\/"},"modified":"2026-06-04T13:16:21","modified_gmt":"2026-06-04T11:16:21","slug":"stubbing-in-python-met-dependency-injector","status":"publish","type":"post","link":"https:\/\/craftcode.be\/nl\/stubbing-in-python-met-dependency-injector\/","title":{"rendered":"Stubbing in Python met Dependency Injector"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Het probleem<\/h2>\n\n<p>Het doel was om deze eerste microservice zo snel mogelijk op te leveren, zonder in te boeten op codekwaliteit. Zo konden de architecturale en technische keuzes meteen gevalideerd worden.<br\/><br\/>Na een eerste analysefase werden OpenAPI-specificaties opgesteld voor vier microservices, waarna de ontwikkeling van alle services gelijktijdig werd opgestart.<br\/><br\/>De developer die werkte aan de aggregatorservice was echter afhankelijk van de drie andere services. Om te vermijden dat de ontwikkeling geblokkeerd werd doordat die services nog niet bestonden, werd gekozen om deze services tijdelijk te stubben.  <\/p>\n\n<h2 class=\"wp-block-heading\">De oplossing<\/h2>\n\n<p><em>Opmerking: in dit voorbeeld wordt FastAPI gebruikt, maar de aanpak is framework-onafhankelijk.<\/em><\/p>\n\n<p>In dit voorbeeld bouwen we een service die basisinformatie over bedrijven teruggeeft, samen met de werknemers die voor dat bedrijf werken.<br\/><br\/>De bedrijfs- en werknemersdata komen uit externe services, zoals:<br\/>\u00b7 andere microservices,<br\/>\u00b7 database calls,<br\/>\u00b7 events,<br\/>\u00b7 of andere databronnen. <\/p>\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"337\" height=\"403\" src=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-3.png\" alt=\"\" class=\"wp-image-147\" srcset=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-3.png 337w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-3-251x300.png 251w\" sizes=\"auto, (max-width: 337px) 100vw, 337px\" \/><\/figure>\n\n<p>De starterapplicatie is terug te vinden in de <code>main<\/code> van deze <code>start<\/code> https:\/\/github.com\/wimvdc\/dependency_injection<\/p>\n\n<p>De uiteindelijke oplossing staat in de main branch.<br\/> <br\/>Voor dependency injection wordt gebruikgemaakt van<a href=\"https:\/\/python-dependency-injector.ets-labs.org\/\" target=\"_blank\" rel=\"noopener\"> Dependency Injecto<\/a>r, een dependency injection framework voor Python.<\/p>\n\n<h2 class=\"wp-block-heading\">1. Stub classes aanmaken<\/h2>\n\n<p>To start, we created a stub class for both <em>company<\/em> and <em>employee<\/em> services.<\/p>\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"503\" src=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-4-1024x503.png\" alt=\"\" class=\"wp-image-148\" srcset=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-4-1024x503.png 1024w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-4-300x147.png 300w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-4-768x377.png 768w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-4.png 1124w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n<p>De eerste stap bestaat uit het aanmaken van een stubklasse voor zowel de company service als de employee service.<br\/><br\/>Deze stubklassen zijn in essentie kopie\u00ebn van de originele classes, inclusief dezelfde methodesignatures.<br\/><br\/>Daardoor kan eenvoudig gewisseld worden tussen de echte implementatie en de stubversie zonder aanpassingen aan de rest van de codebase. <\/p>\n\n<h2 class=\"wp-block-heading\">2. Container configureren<\/h2>\n\n<p>Vervolgens wordt een <code>container.py<\/code> binnen de <code>data<\/code>. Deze container is verantwoordelijk voor het samenstellen van alle dependencies binnen deze laag.<\/p>\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"456\" src=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-6-1024x456.png\" alt=\"\" class=\"wp-image-149\" srcset=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-6-1024x456.png 1024w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-6-300x133.png 300w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-6-768x342.png 768w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-6.png 1160w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n<p>Hier komt Dependency Injector echt in beeld.<br\/> <br\/>De container functioneert als een<a href=\"https:\/\/python-dependency-injector.ets-labs.org\/containers\/declarative.html\" target=\"_blank\" rel=\"noopener\"> declaratieve verzamelin<\/a>g van <a href=\"https:\/\/python-dependency-injector.ets-labs.org\/providers\/index.html\" target=\"_blank\" rel=\"noopener\">providers<\/a>:<br\/>\u00b7 providers cre\u00ebren objecten,<br\/>\u00b7 en injecteren automatisch de juiste dependencies.<br\/> <br\/>In dit voorbeeld wordt een singleton provider gebruikt, maar Dependency Injector ondersteunt ook <a href=\"https:\/\/python-dependency-injector.ets-labs.org\/providers\/index.html\" target=\"_blank\" rel=\"noopener\">andere patronen<\/a> zoals:<br\/>\u00b7 Factory,<br\/>\u00b7 Coroutine,<br\/>\u00b7 en verschillende andere providertypes.   <\/p>\n\n<h2 class=\"wp-block-heading\">3. Wiring voorzien<\/h2>\n\n<p>De volgende stap is het koppelen van de container aan de endpoint of route die de dependency effectief gebruikt.<br\/>Hierbij wordt aan de container doorgegeven in welke modules of packages dependency injection beschikbaar moet zijn.<br\/><br\/>In dit voorbeeld gebeurt dat binnen de application module. <br\/><\/p>\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"840\" height=\"876\" src=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-7.png\" alt=\"\" class=\"wp-image-150\" srcset=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-7.png 840w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-7-288x300.png 288w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-7-768x801.png 768w\" sizes=\"auto, (max-width: 840px) 100vw, 840px\" \/><\/figure>\n\n<h2 class=\"wp-block-heading\">4. Dependencies injecteren<\/h2>\n\n<p>De effectieve dependency injection gebeurt via de <code>@inject<\/code>.<br\/>Daarnaast wordt via de provider uit de container aangegeven welke dependency ge\u00efnjecteerd moet worden.<\/p>\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" src=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-8-1024x608.png\" alt=\"\" class=\"wp-image-151\" srcset=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-8-1024x608.png 1024w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-8-300x178.png 300w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-8-768x456.png 768w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-8-1536x912.png 1536w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-8.png 1596w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n<p>Na deze stap is dependency injection volledig opgezet en kan de applicatie gestart worden.<br\/><br\/>Door de configuratie binnen de container aan te passen, kan eenvoudig gekozen worden tussen de echte implementatie of de stubversie van een service. <\/p>\n\n<h2 class=\"wp-block-heading\">5. Dynamische injection<\/h2>\n\n<p>Het voortdurend aanpassen van <code>container.py<\/code> om dependencies te wisselen is uiteraard niet ideaal. <code>container.py<\/code><br\/>Daarom wordt de container uitgebreid, zodat configuratie uit een extern configuratiebestand gelezen kan worden. Hiervoor wordt een injection.json bestand toegevoegd binnen een nieuwe config folder in de root van het project. <\/p>\n\n<p>Door deze aanpak kan configuratie aangepast worden zonder codewijzigingen. Bovendien maakt dit omgevingsspecifieke configuratie mogelijk.<code>config<\/code><code>injection.json<\/code><\/p>\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"906\" height=\"340\" src=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-9.png\" alt=\"\" class=\"wp-image-152\" srcset=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-9.png 906w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-9-300x113.png 300w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-9-768x288.png 768w\" sizes=\"auto, (max-width: 906px) 100vw, 906px\" \/><\/figure>\n\n<p>In de laatste stap wordt <code>container.py<\/code> aangepast, zodat:<br\/>\u00b7 het configuratiebestand ingelezen wordt,<br\/>\u00b7 en bepaalde providers overschreven kunnen worden wanneer nodig.<\/p>\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"793\" height=\"1024\" src=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-10-793x1024.png\" alt=\"\" class=\"wp-image-153\" srcset=\"https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-10-793x1024.png 793w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-10-232x300.png 232w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-10-768x991.png 768w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-10-1190x1536.png 1190w, https:\/\/craftcode.be\/app\/uploads\/2026\/03\/CraftCode_Blog_StubbinginPython_carbon-10.png 1244w\" sizes=\"auto, (max-width: 793px) 100vw, 793px\" \/><\/figure>\n\n<p>In dit voorbeeld wordt:<br\/>\u00b7 de gestubde versie van de company service gebruikt,<br\/>\u00b7 terwijl voor de employee service de echte implementatie actief blijft.<code>injection.json<\/code> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bij \u00e9\u00e9n van onze klanten werd gestart met het opsplitsen van enkele monolithische applicaties naar REST-gebaseerde microservices.<\/p>\n<p>Voor een eerste use case werden enkele belangrijke services ge\u00efdentificeerd, waaronder een aggregatorservice. Deze service fungeert eigenlijk als een laag die drie andere microservices samenbrengt.<\/p>\n<p>In deze blog bekijken we:  <\/p>\n<p>Hoe dependency injection in Python opgezet kan worden met Dependency Injector,<br \/>En hoe deze dependencies dynamisch gestubd kunnen worden op basis van de omgeving.<\/p>\n","protected":false},"author":1,"featured_media":293,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[55],"tags":[56],"class_list":["post-294","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-technologie"],"acf":[],"_links":{"self":[{"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/posts\/294","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/comments?post=294"}],"version-history":[{"count":1,"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/posts\/294\/revisions"}],"predecessor-version":[{"id":295,"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/posts\/294\/revisions\/295"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/media\/293"}],"wp:attachment":[{"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/media?parent=294"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/categories?post=294"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/craftcode.be\/nl\/wp-json\/wp\/v2\/tags?post=294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}