问题
I am working on an ASP.Net Core MVC Web application.
My Solution contains 2 projects: One for the application and a second project, dedicated to unit tests.
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 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?
Thanks
回答1:
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 _serviceProvide;
public UnitTest1(DbFixture fixture)
{
_serviceProvide = fixture.ServiceProvider;
}
[Fact]
public void Test1()
{
using (var context = _serviceProvider.GetService<SomeContext>())
{
}
}
}
But bear in your mind using EF inside unit test is not good idea and it's better to mock DbContext.
The Anatomy of Good Unit Testing .
回答2:
You can use Xunit.DependencyInjection
回答3:
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
来源:https://stackoverflow.com/questions/50921675/dependency-injection-in-xunit-project