如何使用Autofac

时间:2017-08-24 09:59:24

标签: testing asp.net-core autofac xunit

我正在使用带有Autofac的ASP.NET Core(2.0)和用于集成测试的Microsoft.AspNetCore.TestHost.TestServer。但是,对于某些测试场景,我想注入一些服务模拟而不是ConfigureContainer方法中加载的实现(如下所述:http://docs.autofac.org/en/latest/integration/aspnetcore.html#quick-start-with-configurecontainer)。

示例:

public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .ConfigureServices(s => s.AddAutofac())
            .UseStartup<Startup>()
            .Build();

        host.Run();
    }
}

public class Startup
{
    ...
    public void ConfigureContainer(ContainerBuilder builder)
    {
        builder.RegisterModule(new Modules.ApiModule());
    }
    ...
}

测试类:

public class BasicControllerTests
{
    TestServer server;
    HttpClient client;

    public BasicControllerTests()
    {
        var resellerRepo = new Mock<IResellerProvider>();
        resellerRepo.Setup(a => a.Query())
            .Returns(new[] {
            new Model.Reseller
            {
                Id = Guid.NewGuid(),
                Code = "R1",
                Name = "Reseller 1"
            }
            }.AsQueryable());

        // How to inject mock properly in the lines below?

        server = new TestServer(new WebHostBuilder()
            .ConfigureServices(a => a.AddAutofac())
            .UseStartup<Startup>());

        client = server.CreateClient();
    }
   ...

我想要做的是将TestServer与所有依赖项一起使用,但只是在测试示例中模拟IResellerProvider。实现这一目标的最佳方法是什么?当然,我可以为这个确切的案例创建一个TestStartup类,但我想知道处理这种情况的正确方法是什么。

1 个答案:

答案 0 :(得分:0)

我发现了一个很好的解决方法,可以让您在.net核心api中注入任何其他依赖项。 您将具有此标准代码以在测试中启动

var clientFactory = new WebApplicationFactory<Startup>();
var client = clientFactory.WithWebHostBuilder(builder =>
builder.ConfigureTestServices(services =>
{

}));

var _httpClient = client.CreateClient();

现在您需要将一个Action传递给.ConfigureTestServices,您可以使用它来删除常规应用启动时的注册,并添加另一个可以说是假的注册。这可能是因为如果您使用调试器在服务上,您将看到所有已注册的服务都已存在,并且只需要替换您想要的服务即可。这是我使用的一个简单示例

RemoveVehicleServiceRegistrationFrom(services);
services.AddScoped<IVehicleService, FakeVehicleService>();

在Remove方法中,您只需要查找并删除旧的注册即可。

private static void RemoveVehicleServiceRegistrationFrom(IServiceCollection services)
{
     var vehicleService = services.Single(x => x.ServiceType == typeof(IVehicleService));
     services.Remove(vehicleService);
}

最终版本如下

private HttpClient _httpClient;

[OneTimeSetUp]
public void Setup()
{
    var clientFactory = new WebApplicationFactory<Startup>();
    var client = clientFactory.WithWebHostBuilder(builder =>
        builder.ConfigureTestServices(services =>
        {
            RemoveVehicleServiceRegistrationFrom(services);
            services.AddScoped<IVehicleService, FakeVehicleService>();
        }));

    var _httpClient = client.CreateClient();
}

private static void RemoveVehicleServiceRegistrationFrom(IServiceCollection services)
{
    var vehicleService = services.Single(x => x.ServiceType == typeof(IVehicleService));
    services.Remove(vehicleService);
}