xUnit test execution different dbcontext settings - c#

I'm currently writing xUnit test for a .net core application. This is the way I am setting up my DbContext in the Startup:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
Now I want the xUnit tests to be executed using SQLite, which would require me to be able to detect if the application is being executed normally or if the tests are being executed in my Startup Class. To then set up the DbContext depending on that.
Is there a way to do so? I have been googling a lot, but not been able to find a good solution.

Trying to understand what you want to do. I am not sure I got it but I can give some tips.
If you want to test the database in unit tests with EF you can do the following.
Create a context options builder object, using an in memory database
var options = new DbContextOptionsBuilder<YourContext>()
.UseInMemoryDatabase(databaseName: "TestingDb")
.Options;
Create a context using this options object
var context = new YourContext(options);
And create a repository using the above context.
_repository= new YourRepository(context);
Now use this new repository and you will have a proper in memory database for your tests. Using DbContextOptionsBuilder you can change the target database as you wish. I hope my answer helps you.

Related

Mock Database.GetDbConnection

Please help with ideas how can i mock someDbContext.Database.GetDbConnection()?
Currently i have repository pattern and the only concrete database context, which injected there. And in unit tests i want to test behavior of AddSomeEntity abd RemoveSomeEntity method, where, exactly, i use someDbContext.Database.GetDbConnection() to get dbConnection and after that create dbCommand and execute it.
I know few ways how i can solve this problem: add abstraction or some logic in repository class, but it seems like overcomplicated. So i'm asking for any ideas, how can i mock this method call directly in unit test class without adding any classes or method in source class.
I'm using EF Core 6, xUnit, Moq and FluentAssertions, i tried, but there wasn't appropriate solution.
How i currently mock db context
contextMock.Setup(x => x.SomeDbSet)
.ReturnsDbSet(new List<SomeEntity>
{
new()
{
// initialization of class fields
}
});
If you are using a Repository pattern, that is the perfect boundary for unit testing/mocking. Unit tests test business logic so the repository is the one mocked to provide known data state and/or assert that proper calls are made to persist data state.
In my case my repositories leverage IQueryable so I utilize MockQueryable.Moq now for wrapping known sets as IQueryable to work with both synchronous and asynchronous consumption.
To test the repository implementation itself, that I would recommend treating at an integration test level using a live data source. This could be a database which a pre-known initial data state or an in-memory database. The behaviour of in-memory databases can differ from actual databases so I tend to use backup DB images for integration tests.

How to use PooledDbContextFactory without DI

We are updating an application to ASPNET .NET 6 and EF Core 6. The application started without DI. Currently, we are creating a new DBContext () for each query. We want to switch to inject the DBContext, however for all current code we want to use PooledDbContextFactory to avoid creating the context on every query.
We would like to know how this implementation should be in an ASPNET application. We are testing by saving the pool to a ThreadLocal <PooledDbContextFactory <DBContext>> object to reuse the pool. Also we have test with a private static readonly Lazy<PooledDbContextFactory<DBEntities>> object.
This is a correct way? Should or can it be done in another way? Is this use correct?

Parallel integration testing with SQL database

Wanted Result: Run integration tests in parallel with entity framework configured to use some kind of database that enforces constraints.
Current Situation: I have a project with some integration tests, and by that I mean test set up with WebApplicationFactory<Startup>. Currently I use it with EF Core setup to use In Memory Database
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
ConfigureWebHostBuilder(builder);
builder.ConfigureTestServices(services =>
{
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
services.AddDbContext<AppDbContext>(options =>
{
options.UseInMemoryDatabase("testDb");
options.UseInternalServiceProvider(serviceProvider);
options.EnableDetailedErrors();
options.EnableSensitiveDataLogging();
});
});
}
While this works, the problem is that it doesn't enforce SQL queries and I already ran in multiple cases where integration tests show the feature works, but when trying to reproduce it with actual project running and having EF connected to SQL Server database, the feature fails because of some failed database constraint.
Ideas:
At first I thought of using SQLite in memory database. Didn't work, I think it's some concurrency issue, because at the start of every test case, I wipe the database with .EnsureDeleted() .EnsureCreated() .Migrate()
Then SQLite with files with random names. Didn't work, because I couldn't manage to wipe out internal DbContext Cache. I was sure that file was recreated and clean, but DbContext simply had cached entities.
Finally after some migrations I released that I wouldn't probably be able to use SQLite at all, because it doesn't support a lot of migration types (Removing FK, altering a column, etc.)/

UseInMemoryDatabase context isn't being shared across unit tests

I'm using Entity Framework Core 2.0-preview1 with InMemory 2.0-preview1.
Each unit test class inherits a disposable class that creates a new in-memory database that its parents can use.
public Constructor()
{
var services = new ServiceCollection();
services.AddEntityFrameworkInMemoryDatabase()
.AddDbContext<DBContext>(o => o.UseInMemoryDatabase("Test"));
var serviceProvider = services.BuildServiceProvider();
Context = serviceProvider.GetRequiredService<DBContext>();
}
The issue with giving the database a name is that it cannot be shared across multiple tests, and thus each test creates a new context resulting in each unit test lasting a few seconds, which is unacceptable for my build server. I can't find much documentation on why this was changed in 2.0 or how to get past this.
I've tried using the new .UseTransientInMemoryDatabase, but this appears to change nothing.
I used a xUnit fixture to provide all my test instances with the save database context. That way I avoid the context creation overhead on each test which speeds the build server up by a large margin.

Using Migrations with Effort.EF6?

I'm using EF6 and I'm now setting up some tests for my aggregates. I've decided to use Effort.EF6 because I'd like to have those tests run without having to install an entire database engine.
My DbContext uses migrations and a seeding method that inserts some data. Can Effort.EF6 make use of that or should I use Effort's methods of seeding data ?
The migrations take place automatically. I call the normal context seed method when I need populated data. Note that depending on the scope of your context (per test, or per test assembly) you may be running lots and lots of queries to do your seeding. That has both performance implications, and debugging issues, since any seeding bugs will start showing up as bugs in your tests, and any logging that happens during seeding will log as part of each test.
var connection = Effort.DbConnectionFactory.CreateTransient();
var context = new DbContext(connection);
context.Seed();

Categories

Resources