❔ Help needed to clear database with EF between XUnit tests
I don't understand how to clear in memory database properly between tests with XUnit.
I mean, I already tried a lot of stuff to do: EnsureDeleted/Created, Manual deletion, clearing the tracker.
Probably I am missing something important here but I don't get what.
34 Replies
where does InitAsync get called from?
ok, so it gets called from xunit. Have you observed this whn debugging?
dont you need to 'SaveChanges' at the end of the method?
Yes, I did and it did not help me either.
I tried manual deletion of entities, tried EnsureDeleted/Created, Tried to clear change tracker and so on
I have a rough guess that all the tests are executed in parallel and each test shares the same database context
But I am not sure about it
xunit runs classes in parallel, not methods
by default
Yes, but as I understand, for each test it creates new instance of the test class
Yes. What kind of fixture are you using for the webAppFactory ?
Default one from Microsoft.AspNetCore.Mvc.Testing
I was referring to the xunit type of fixture
So if you want a separate db per test, why use class fixture?
I am sorry, what I do may sound stupid but I am really new to the asp net.
Basically I made this project 4 days ago
(migrating from java/spring btw)
If you want something new for each test, the normal way is to 'new' it in the constructor
So, I made tests green by applying
Collection
attribute to the base classSo, the problem here definitely with the shared db context
what type of in-memory db are you using?
Yes, but what I am trying to achieve is subcutaneous testing, so I want to test the core of my application as close to the real-world scenario as possible
later on I will add pgsql and testcontainers
Microsoft.EntityFrameworkCore.InMemory
What you say is not consistent with the tests though
you want 'real life tests', but then want to test in isolation from scratch every time?
And you are blocking out parallel tests by adding Collection attribute
So first, what do you want?
I have a few use cases in my application and I want to test them with the actual database rather than mocked one. As I said, later I will switch in memory db adapter to pgsql.
So actually, you want simple small tests, and to use a fresh db each time?
Yes, but not only a database but a whole context with it: MediatR, FluentValidators, and other services that are registered inside the Program.cs
btw, ms explicitly warns against using the EF in-mem db for actually doing DB stuff
Yeah, I saw that one. I just needed something to catch up quickly with asp.net and choose the in memory one
ok. Well, you can specify the name of the db - you can choose a different one for each test
But again, this is going the per-test route, not the class fixture route
Well, I have an idea.
I may try to turn db context into transient rather than scoped. But I feel like this is a fools path as the result is unclear for me
that definitely does not jive with "I want to test the core of my application as close to the real-world scenario as possible"
and also does not fix anything
Oh, so basically I can just generate the unique database for each separated test?
That makes sense!
you need to configure the context/db builder differently, yes
like here
https://learn.microsoft.com/en-us/ef/core/testing/testing-without-the-database#in-memory-provider
But I did not understand you when you said "per-test" vs "per class fixture"
Will I be able to use this same approach with the real database?
no, because you cannot create multiple databases with postgres (e.g.) just by pasting a different name into the connection string
Well, I guess then I will be forced to execute tests inside separated docker environments...
That's a little bit too expensive
Well, thank you very much anyway!
I was struggling with this issue the whole day, and now I have an understanding of what went wrong and that I have some misconceptions on my side
It seems odd that you want multiple test sets to run against an actual db, you want them to run in parallel, but you dont want them on the same db
Well, honestly speaking I didn't think about how all of this works under the hood and how much control I have over it. Thank you again for pointing this out to me.
The reason why I want to test the core with an actual database is that I want to have guarantees that a specific build works with that specific database.
Sure. But there is generally a small amount of full system tests when compared to the number of unit/component tests.
So I wouldnt expect to see a test for 'api endpoint adds one entity to the real db'
Totally agree with you, but that if you have a system at scale.
What I do Is a simple CRUD where adding an entity to the db is the core usecase 🙂
Let me put it like this, if you have more tests that are at a service level where you have the real service, interacting with the real db, then yes, you would have plenty of crud tests on the service, and also performance/stress test and parallel tests.
Then aside from that, there could be numerous very thin tests that check the ASP.NET endpoints send the correct data to mocked services.
You of course would have a limited number of full system tests.
What I'm saying is that you do not need to be testing the entirety of the app functionality via full system tests.
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.