代码之家  ›  专栏  ›  技术社区  ›  itim

如何正确配置模拟依赖项以使用Autofac测试Web Api(ASP.NET Core)控制器

  •  4
  • itim  · 技术社区  · 7 年前

    Autofac 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 回复  |  直到 7 年前
        1
  •  3
  •   TheMyrel    5 年前

    我找到了一个解决方法,它可以很好地工作,并允许您在其中注入任何其他依赖项。net core api。 您将在测试中启动此标准代码

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

    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);
    }