是否可以在xUnit中使用依赖注入?

时间:2016-08-24 19:05:23

标签: unit-testing testing dependency-injection ioc-container xunit

我有一个带有需要IService的构造函数的测试类。

public class ConsumerTests
{
    private readonly IService _service;
    public ConsumerTests(IService servie)
    {
      _service = service;
    }

    [Fact]
    public void Should_()
    {
       //use _service
    }
}

我想插入我选择的DI容器来构建测试类

这可以用 xUnit 吗?

4 个答案:

答案 0 :(得分:4)

是的,我认为这两个问题和答案应该合并,请参阅此处的答案

Net Core: Execute All Dependency Injection in Xunit Test for AppService, Repository, etc

在下面使用“自定义Web应用程序工厂”和“ ServiceProvider.GetRequiredService”,随时编辑和优化答案

CustomWebApplicationFactory:

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureAppConfiguration((hostingContext, configurationBuilder) =>
        {
            var type = typeof(TStartup);
            var path = @"C:\\OriginalApplication";

            configurationBuilder.AddJsonFile($"{path}\\appsettings.json", optional: true, reloadOnChange: true);
            configurationBuilder.AddEnvironmentVariables();
        });

        // if you want to override Physical database with in-memory database
        builder.ConfigureServices(services =>
        {
            var serviceProvider = new ServiceCollection()
                .AddEntityFrameworkInMemoryDatabase()
                .BuildServiceProvider();

            services.AddDbContext<ApplicationDBContext>(options =>
            {
                options.UseInMemoryDatabase("DBInMemoryTest");
                options.UseInternalServiceProvider(serviceProvider);
            });
        });
    }
}

集成测试:

public class DepartmentAppServiceTest : IClassFixture<CustomWebApplicationFactory<OriginalApplication.Startup>>
{
    public CustomWebApplicationFactory<OriginalApplication.Startup> _factory;
    public DepartmentAppServiceTest(CustomWebApplicationFactory<OriginalApplication.Startup> factory)
    {
        _factory = factory;
        _factory.CreateClient();
    }

    [Fact]
    public async Task ValidateDepartmentAppService()
    {      
        using (var scope = _factory.Server.Host.Services.CreateScope())
        {
            var departmentAppService = scope.ServiceProvider.GetRequiredService<IDepartmentAppService>();
            var dbtest = scope.ServiceProvider.GetRequiredService<ApplicationDBContext>();
            dbtest.Department.Add(new Department { DepartmentId = 2, DepartmentCode = "123", DepartmentName = "ABC" });
            dbtest.SaveChanges();
            var departmentDto = await departmentAppService.GetDepartmentById(2);
            Assert.Equal("123", departmentDto.DepartmentCode);
        }
    }
}

资源:

https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2

https://fullstackmark.com/post/20/painless-integration-testing-with-aspnet-core-web-api

答案 1 :(得分:2)

你想测试什么? IService的实施或DI容器的接线?

如果您正在测试IService实现,您应该直接在测试中实例化它们(并模拟任何依赖项):

var service = new MyServiceImplementation(mockDependency1, mockDependency2, ...);
// execute service and do your asserts, probably checking mocks

如果您正在尝试测试DI容器的接线,则需要伸出手并明确抓取已配置的容器。没有&#34;组成根&#34;这将为你做到这一点(伪代码跟随,Autofac口味):

var myContainer = myCompositionRoot.GetContainer();
var service = myContainer.ResolveCompnent<IService>();
// execute service and do your asserts with the actual implementation

如果您正在使用xUnit运行集成测试,您需要在多个测试中使用相同的对象,请查看Fixtures:http://xunit.github.io/docs/shared-context.html

答案 2 :(得分:2)

有一种方法可以使用此源代码中的nuget包执行此操作:https://github.com/dennisroche/xunit.ioc.autofac

只要您使用[Fact],它就会很有效,但是当我开始使用[Theory]时,我会被阻止。有一个拉取请求可以解决这个问题。

为了解锁我自己,我使用CollectionFixture注入Container,并从容器中解析接口。

答案 3 :(得分:0)

是的,可以使用Xunit.DependencyInjection

Install-Package Xunit.DependencyInjection

您就可以注入服务

[assembly: TestFramework("Your.Test.Project.Startup", "AssemblyName")]

namespace Your.Test.Project
{
    public class Startup : DependencyInjectionTestFramework
    {
        public Startup(IMessageSink messageSink) : base(messageSink) { }

        protected override void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<IDependency, DependencyClass>();
        }
    }
}

https://github.com/pengweiqhca/Xunit.DependencyInjection