Xunit项目中的依赖注入

时间:2018-06-19 06:12:24

标签: dependency-injection asp.net-core-mvc xunit

我正在开发一个ASP.Net Core MVC Web应用程序。

我的解决方案包含2个项目:一个用于应用程序,另一个项目用于单元测试。

我在测试项目中添加了对应用程序项目的引用。

我现在要做的是在Tests项目中编写一个类,它将通过实体框架与数据库进行通信。

我在我的应用程序项目中所做的是通过构造函数依赖注入来访问我的DbContext类。

但我不能在我的测试项目中这样做,因为我没有Startup.cs文件。在这个文件中,我可以声明哪些服务可用。

那么我该怎样做才能在测试类中获得对DbContext实例的引用?

谢谢

4 个答案:

答案 0 :(得分:5)

您可以实施自己的服务提供商来解决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>())
        {
        }
    }
}

但是在你的脑海中使用EF内部单元测试并不是一个好主意,最好是模拟DbContext。

The Anatomy of Good Unit Testing

答案 1 :(得分:1)

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

答案 2 :(得分:0)

您可以使用Xunit.DependencyInjection

答案 3 :(得分:0)

您可以使用包 Microsoft.EntityFrameworkCore.InMemory

var _dbContextOptions = new DbContextOptionsBuilder<DbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;

然后

var context = new DbContext(_dbContextOptions);