Reputation: 9163
I am working on an ASP.Net Core MVC Web application.
My Solution contains 2 projects:
I have added a reference to the application project in the Tests project.
What I want to do now is to write a class in the XUnit Tests project which will communicate with the database through entity framework.
What I was doing in my application project was to access to my DbContext
class through constructor dependency injection.
But I cannot do this in my tests project, because I have no Startup.cs
file. In this file I can declare which services will be available.
So what can I do to get a reference to an instance of my DbContext
in the test class?
Upvotes: 35
Views: 44049
Reputation: 11554
You can implement your own service provider to resolve DbContext
.
public class DbFixture
{
public DbFixture()
{
var serviceCollection = new ServiceCollection();
serviceCollection
.AddDbContext<SomeContext>(options => options.UseSqlServer("connection string"),
ServiceLifetime.Transient);
ServiceProvider = serviceCollection.BuildServiceProvider();
}
public ServiceProvider ServiceProvider { get; private set; }
}
public class UnitTest1 : IClassFixture<DbFixture>
{
private ServiceProvider _serviceProvider;
public UnitTest1(DbFixture fixture)
{
_serviceProvider = fixture.ServiceProvider;
}
[Fact]
public void Test1()
{
using (var context = _serviceProvider.GetService<SomeContext>())
{
}
}
}
But bear in your mind using EF inside a unit test is not a good idea and it's better to mock DbContext.
The Anatomy of Good Unit Testing
Upvotes: 45
Reputation: 1
You can to use package Microsoft.EntityFrameworkCore.InMemory
var _dbContextOptions = new DbContextOptionsBuilder<DbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
And then
var context = new DbContext(_dbContextOptions);
Upvotes: 0
Reputation: 251
For unit tests you need to mock your context.
There is a great nuget package for mocking that is called Moq.
Some help to get you started:
public ClassName : IDisposable
{
private SomeClassRepository _repository;
private Mock<DbSet<SomeClass>> _mockSomeClass;
public ClassName()
{
_mockSomeClass = new Mock<DbSet<SomeClass>>();
var mockContext = new Mock<IApplicationDbContext>();
mockContext.SetupGet(c => c.SomeClass).Returns(_mockSomeClass.Object);
_repository = new SomeClassRepository(mockContext.Object);
}
public void Dispose()
{
// Anything you need to dispose
}
[Fact]
public void SomeClassTest()
{
var someClass = new SomeClass() { // Initilize object };
_mockSomeClass.SetSource(new[] { someClass });
var result = _repository.GetSomethingFromRepo( ... );
// Assert the result
}
}
For integration tests you do the same thing but the setup is:
_context = new ApplicationDbContext();
Make sure that your TestClass
inherits from IDisposable
(TestClass : IDisposable
) so that you can dispose the context after each test.
https://xunit.github.io/docs/shared-context
Upvotes: 0