The Best Way To Use Docker For Integration Testing In .NET

แชร์
ฝัง
  • เผยแพร่เมื่อ 2 มิ.ย. 2024
  • Get the source code for this video for FREE → the-dotnet-weekly.ck.page/tes...
    ☄️ Master the Modular Monolith Architecture: bit.ly/3SXlzSt
    📌 Accelerate your Clean Architecture skills: bit.ly/3PupkOJ
    🚀 Support me on Patreon to access the source code: / milanjovanovic
    Integration testing is a testing approach that tests the integration between multiple components. Usually, this will involve a database, so you can test your query logic. Docker is an excellent tool for creating throwaway databases for your integration tests. And you can make it even better with the Testconatiners library. It allows you to programmatically create your docker containers for integration testing.
    Testcontainers - Integration Testing Using Docker In .NET
    www.milanjovanovic.tech/blog/...
    Join my weekly .NET newsletter:
    www.milanjovanovic.tech
    Read my Blog here:
    www.milanjovanovic.tech/blog
    Subscribe for more:
    / @milanjovanovictech
    Chapters:
    0:00 Creating the test project and installing Testcontainers
    1:55 Implementing a custom WebApplicationFactory
    6:11 Adding a PostgreSQL container with Testcontainers
    8:15 Creating the base integration test class
    9:57 Integration test 1: Creating a product with exception
    13:10 Integration test 2: Creating a product and validating in the database
    16:13 Integration test 3: Getting a product by the ID
  • วิทยาศาสตร์และเทคโนโลยี

ความคิดเห็น • 111

  • @MilanJovanovicTech
    @MilanJovanovicTech  9 หลายเดือนก่อน +4

    Get the source code for this video for FREE → the-dotnet-weekly.ck.page/testcontainers

  • @ndanh1
    @ndanh1 9 หลายเดือนก่อน +4

    Finally this day has come! I know once day you will touch this topic. I'm applying this topic on both my side and main projects.

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +2

      I'm surprised how many people are excited about this topic, you included 😁

  • @ernestmfakudze
    @ernestmfakudze 9 หลายเดือนก่อน +1

    Thanks very much for this. I've always struggled with Integration Testing and this clarified it for me.

  • @eja7444
    @eja7444 9 หลายเดือนก่อน +12

    Dude, if you ever wrote a book, I got first dibs on it. 😊

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +2

      The course will have to be enough for now 😅
      What should the book be about? 🤔

    • @ruslan_yefimov
      @ruslan_yefimov 11 วันที่ผ่านมา

      @@MilanJovanovicTech About communism, obviously

  • @nove1398
    @nove1398 9 หลายเดือนก่อน +1

    About time you do this type of video, you need to do more docker work!

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +1

      Any specific topics?

    • @nove1398
      @nove1398 9 หลายเดือนก่อน

      @@MilanJovanovicTech docker compose, if you think it makes sense to you

  • @nnaemekaeziamaka7116
    @nnaemekaeziamaka7116 9 หลายเดือนก่อน +1

    Beautiful! Just Beautiful!

  • @darylbeaumont8855
    @darylbeaumont8855 หลายเดือนก่อน

    This is a great resource and had really helped with integration testing. Thank you for your work covering this topic/technology!

  • @majormartintibor
    @majormartintibor 9 หลายเดือนก่อน

    Excellent video!

  • @mbsa220
    @mbsa220 9 หลายเดือนก่อน +1

    Great and informative thanks

  • @audreyernestodelima7025
    @audreyernestodelima7025 9 หลายเดือนก่อน +1

    every video is mind blowing

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      That's a high standard to live up to 😅

  • @Flanno91
    @Flanno91 9 หลายเดือนก่อน +1

    I think this is one of your most helpful videos yet Milan. Given that once you've done the boilerplate to set this up, it's actually pretty easy to write additional tests, would you say this is a good substitute for unit tests as you don't need to mock anything? Or would you still use unit tests alongside this method?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      I would definitely prefer this over unit test handlers, yes! I'm also writing a newsletter about this right now, and I'll share all the code on GitHub.
      P.S. Thanks a lot! I'm working on improving the quality of the videos after releasing my course, and I'm glad it shows.

  • @porcinetdu6944
    @porcinetdu6944 9 หลายเดือนก่อน

    Very good thank you. I like the explication about the program class at the beginning. Kind of not necessary but making everything super clear

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      Sometimes I like to cover all the bases

  • @julienlefevre1661
    @julienlefevre1661 9 หลายเดือนก่อน +5

    Hey, thanks, nice video. Would be also nice to have explainations concerning integration tests in deployed DEV and STAGING environments using CI. Thanks for the job done ;)

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +6

      Maybe in a future video, good idea 👌

  • @watchchat
    @watchchat 3 หลายเดือนก่อน

    This is a great topic! I haven’t finished the video but the one improvement I’d add is to not have credentials hard-coded in the source. Showing the noobs the correct way to implement that would give them a head start on being a better dev that thinks about security.

    • @MilanJovanovicTech
      @MilanJovanovicTech  3 หลายเดือนก่อน

      Where did I hard code them in the source? 🤔

  • @palashchoudhary112
    @palashchoudhary112 9 หลายเดือนก่อน +1

    Man... I got so many comments saying you should use count 1.... Thanks for clearing the doubts.

  • @madhu-sameena
    @madhu-sameena 7 หลายเดือนก่อน +1

    Thank you for the cool content, This is is really interesting
    I used SQLite or in memory for my API Tests so far, but this is nice.
    It would be great, if you can release one video with calling APIs in tests and also apply the migrations to replicate the real scenario

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 หลายเดือนก่อน +2

      Working on a part 2 with more details :)

  • @benlewies8828
    @benlewies8828 9 หลายเดือนก่อน +1

    Great stuff, Milan. Why not use Selenium IDE for running your web tests (alongside Docker for setting up your infrastructure)?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      I don't typically write automated UI tests

  • @sunnypatel1045
    @sunnypatel1045 8 หลายเดือนก่อน +1

    Great stuff Milan. Had one question is there a way to not use EFCore? I got a project that just uses SqlConnection which calls a store proc and in the settings I am passing only a connection string.

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน +1

      Sure, why not? Just write some good ol' SQL 😁 Dapper is a good choice.

  • @svenscekic2240
    @svenscekic2240 3 หลายเดือนก่อน

    Great video as always. Just one question does this approach initalize a docker container for each test class or only one container for all test classes?

    • @MilanJovanovicTech
      @MilanJovanovicTech  3 หลายเดือนก่อน

      It's one container per fixture, not the IClassFixture implementation here: th-cam.com/video/tj5ZCtvgXKY/w-d-xo.html
      What does this mean in practice? All tests within a single test class will reuse the same container instances.
      Test cases from different test classes will have different containers.
      You can implement an ICollectionFixture, to share containers across all tests within a collection.
      Or, you can manually create a new container for each test.

  • @thespicycoder5583
    @thespicycoder5583 9 หลายเดือนก่อน +1

    Great Video.
    When you perform Build & Test inside Docker containers, using test containers might not work.
    As Integration tests are already being executed within a container & you want to spin up a container within a container.
    Any workarounds?
    Thanks

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      Containerception. What environment would you be running that in?

    • @thespicycoder5583
      @thespicycoder5583 9 หลายเดือนก่อน

      @@MilanJovanovicTech Say, Azure DevOps or a Self hosted Kubernetes Cluster

  • @vincentbenazet3137
    @vincentbenazet3137 8 หลายเดือนก่อน +1

    Great Video, I don't understand how you set up your database structure. Does it do it automatically through the DbContext configuration? If I have foundational data, can I use Entity Framework migrations, or do I need to generate an SQL script for that ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน +1

      I run EF migrations at startup (web app factory setup).

    • @pola587
      @pola587 7 หลายเดือนก่อน

      @@MilanJovanovicTech so do you run it after you start async right or how you do it ?

    • @juankar008
      @juankar008 6 หลายเดือนก่อน

      I think is the config that starts at minute 5:30 of the video.

  • @kostasgkoutis8534
    @kostasgkoutis8534 9 หลายเดือนก่อน

    What about customizing the data inside the container? I see you added a volume, but every test refers to it. Would you tweak them as part of the Arrange section or is there some other strategy you can employ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      Test container is separate from my docker compose ond

    • @kostasgkoutis8534
      @kostasgkoutis8534 9 หลายเดือนก่อน

      @@MilanJovanovicTech ah I see, makes sense.

  • @km-9ra
    @km-9ra 6 หลายเดือนก่อน +1

    Hey Milan great video, thanks! Is there a way to use the testcontainers package with a CosmosDB? 🙂

  • @devlife013
    @devlife013 9 หลายเดือนก่อน +2

    Thanks for the amazing video.
    Just a question, how about using an interface in API and then reference it to the test?
    Something like :
    public interface IMarker { }

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      What would the interface be for?

    • @devlife013
      @devlife013 9 หลายเดือนก่อน

      @@MilanJovanovicTech in case of using the partial class in program.cs would it also be possible to include this interface in API project and then reference it to test project?
      The interface is just a marker and would be empty.

  • @vekzdran
    @vekzdran 9 หลายเดือนก่อน

    Milan, excellent video, I am just working on this setup so video came in perfect time. I missed one thing. I guess the SQL service in the container pings back when its actually started and that signals the StartAsync to have a successful result? Also, I guess, you do DB migrations up in your Program/Startup logic when the factory goes through. I am asking as I need to do exactly this, migrate up a new instance of DB schema at one point and I guess its is OK in StartAsync after container is spinning? Ideas? Thx!

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +1

      Yeah, creating DB is done in Program, I omitted that.

    • @TheDrComedy
      @TheDrComedy 9 หลายเดือนก่อน

      @@MilanJovanovicTech Is it possible to do a full video on how you created the db schema inside your container?

  • @wojtas1989
    @wojtas1989 9 หลายเดือนก่อน +3

    Great video Milan!
    One thing bothers me as I see shadowing methods as a huge red flag and problem causer.
    I'm just thinking that explicit interface implementation would be much better here. and if not, then why not to override DisposeAsync with line you've put and call to base implementation?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +1

      Given this is a test class, I think the decision was justified for simplicity. For a more correct solution, your approach is fine 👌

  • @rareschelariu5327
    @rareschelariu5327 9 หลายเดือนก่อน +1

    How would you approach schema creation and seeding in an app that doesn't use EF (repositories execute raw SQL or stored procedura) ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +2

      Just run some SQL

    • @rareschelariu5327
      @rareschelariu5327 9 หลายเดือนก่อน

      @@MilanJovanovicTech Of course - managed to do that successfully - I was thinking about structuring of files and versioning, bearing in mind that the TestContainers always points to master DB in the Conn String and regarding SQL SERVER the GO instruction can not be run from remote SQL calls (can not create multiple stored procedures in one statement)

    • @pilotboba
      @pilotboba 9 หลายเดือนก่อน

      @@MilanJovanovicTech Is there any way for Testcontainers to use your/a docker-compose file rather than having to define the service containers in code which are already defined in your docker-compose file?

  • @TrungTran-le2ht
    @TrungTran-le2ht 2 หลายเดือนก่อน

    Thanks for the content.
    I have a question : what are the Pros and Cons when using TestContainer over the WireMock ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 หลายเดือนก่อน

      WireMock is for API mocking (HTTP) right?

    • @TrungTran-le2ht
      @TrungTran-le2ht 2 หลายเดือนก่อน

      @@MilanJovanovicTech
      Edit: i just read the document and seems like TestContainers has a wrapper for WireMock but not vice versa.
      yes. I know they are different tools but can we use one to replace another ?

  • @porcinetdu6944
    @porcinetdu6944 9 หลายเดือนก่อน +1

    I am wondering would not it be possible to share the docker instance among all the tests. Each would create a database and not a whole container to save ressources and reduce the overall test time.

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +2

      That's a great point. Let me try to find some resources around that

    • @user-bx2er2zx5u
      @user-bx2er2zx5u 9 หลายเดือนก่อน

      It's possible if use Respawner library and clear db after each test

    • @porcinetdu6944
      @porcinetdu6944 9 หลายเดือนก่อน

      @@MilanJovanovicTech I have been able to do it (with mongo DB using another package to fit my project). I share a singleton using fixture and fixture collection

    • @nove1398
      @nove1398 9 หลายเดือนก่อน

      @@porcinetdu6944 fixture collection creates a singleton?

  • @damjantadic
    @damjantadic 5 หลายเดือนก่อน +1

    Is there a way to specify the build configuration for the container using appsettings?

    • @MilanJovanovicTech
      @MilanJovanovicTech  5 หลายเดือนก่อน

      Can you be more specific? 🤔

    • @damjantadic
      @damjantadic 5 หลายเดือนก่อน

      @@MilanJovanovicTech For example the parameters for WithDatabase() WithUsername() WithPassword() I want to get from appsettings.

  • @KenzoArts
    @KenzoArts 23 วันที่ผ่านมา

    Will the database in the the docker container have the same schema and data that exist in my physical SQL server database?
    In my sql server database i have some sql views and functions that i use in my handlers to fetch data.

    • @MilanJovanovicTech
      @MilanJovanovicTech  23 วันที่ผ่านมา

      Yes, if you recreate that structure with migration scripts

  • @user-ge1nt6dp6c
    @user-ge1nt6dp6c 9 หลายเดือนก่อน +2

    How does this work without running the migrations on the docker database?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +2

      Migrations are executed at startup in Program, omitted that part

  • @matthewrossee
    @matthewrossee 9 หลายเดือนก่อน

    What is the difference between minimal api approach and api with controllers in 3:45? How should I do that with controllers?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      Well Program.cs is already public there?

    • @user-bx2er2zx5u
      @user-bx2er2zx5u 9 หลายเดือนก่อน

      no difference - just write this line in your program.cs

    • @pilotboba
      @pilotboba 9 หลายเดือนก่อน

      @@MilanJovanovicTech Not if you use top level statements with controllers. You still need to add the partial public visible class afaik.

  • @sasanarham
    @sasanarham 4 หลายเดือนก่อน

    Thank you Milan for your easy-to-follow videos. Do you have any recommendations for learning best practices in integration tests?
    For example for "Unit Test" I really like this book: "The Art Of Unit Testing" by ROY OSHEROVE

    • @MilanJovanovicTech
      @MilanJovanovicTech  4 หลายเดือนก่อน

      There could be a book like that, but I haven't read it yet, so can't recommend anything

  • @user-bx2er2zx5u
    @user-bx2er2zx5u 9 หลายเดือนก่อน +1

    These tests also need something like Respawner library to clear containers db after test execution. Thanks to it a collection of tests can use one container.

    • @pilotboba
      @pilotboba 9 หลายเดือนก่อน +1

      Another option is to not put all the tests into the fixture, so it will spin up a container for each test. Of course, this will add overhead and time to your test runs.

    • @user-bx2er2zx5u
      @user-bx2er2zx5u 9 หลายเดือนก่อน

      @@pilotboba no way , if there are 30 tests - it will start 30 containers!

    • @pilotboba
      @pilotboba 9 หลายเดือนก่อน

      @@user-bx2er2zx5u Maybe. A few things.
      Linux containers are lightweight and fast. So maybe 30 containers isn't a problem.
      You only have to isolate db stuff where one test will conflict with another.
      Another option, write your tests so those data conflicts don't happen. Have each test clean up after itself.
      Id prefer all these before I bring in some tool to clean the db.

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      What if each test handles its own data?

    • @user-bx2er2zx5u
      @user-bx2er2zx5u 9 หลายเดือนก่อน

      @@MilanJovanovicTech every test manages it's data and clear it after execution using Respawner

  • @KenB782
    @KenB782 5 หลายเดือนก่อน

    Are the migrations automatically applied to the container? (Only question I have)

    • @MilanJovanovicTech
      @MilanJovanovicTech  5 หลายเดือนก่อน

      Yes (at app startup)

    • @KenB782
      @KenB782 5 หลายเดือนก่อน

      @@MilanJovanovicTech Thank you 😊

  • @usamesavas9848
    @usamesavas9848 8 หลายเดือนก่อน +1

    Why don't you test against API endpoints instead of Service methods?

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน

      Simpler

    • @usamesavas9848
      @usamesavas9848 8 หลายเดือนก่อน

      @@MilanJovanovicTech I see. Besides, you can test the controllers in isolation at the same time.
      One problem I faced with testing API endpoints with test containers is that it fires up a distinct container for each http request even in the same test method so I cannot “get” a database row I just added with a “post” request.

  • @petewarner1077
    @petewarner1077 9 หลายเดือนก่อน

    Great content as usual, Milan!
    I think that dispatching commands/queries directly via MediatR shortcuts the WebApi itself - a key part of the application infrastructure. In that sense, it's not a full integration test because you'll not test logic in the HTTP Middleware (such as Auth) or any code sitting in the endpoint handlers that runs before mediatR.Send
    Would love to see this revisited but using the HttpClient directly to call the API, perhaps including how to (for example) configure the app in testing to expect test bearer tokens.

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน +1

      I'm fine with bypassing the HTTP request pipeline because there is little value in writing a lot of functional tests. A few of them are definitely helpful, but I think having more integration tests like these is beneficial.

  • @muumitramm
    @muumitramm 9 หลายเดือนก่อน +1

    Why should i use temporary database if i just could use Moq to mock the database. No need to spin up anything. :)

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      Because you might as well be using in-memory data. Why even have a database?

    • @muumitramm
      @muumitramm 9 หลายเดือนก่อน

      @@MilanJovanovicTech yeah. That was my idea but tests are calling methods that have db queries inside. Those should be mocked as well.