【问题标题】:Mock service for xUnitxUnit 的模拟服务
【发布时间】:2019-08-22 21:13:06
【问题描述】:

我有一个当前按设计工作的应用程序,但我正在尝试使用 xUnit 设置集成测试,然后再对其进行扩展。目前测试在执行测试时只会使用原始服务,我不明白为什么。

这就是测试:

using IStoreRepository = Repositories.V3.Interfaces.IStoreRepository;

public class StoreTests : IClassFixture<WebApplicationFactory<Startup>> {
    private readonly ITestOutputHelper _output;
    private readonly WebApplicationFactory<Startup> _factory;
    private readonly string _url;

    public StoreTests(ITestOutputHelper output, WebApplicationFactory<Startup> factory) {
        _output = output;
        _factory = factory;

        _url = "/api/store";
    }

    [Theory]
    [InlineData("GET", "FAKE123")]
    public async Task StoreByCode(string method, string code = null) {
        // var client = _factory.CreateClient();

        var client = _factory.WithWebHostBuilder(builder => {
            builder.ConfigureTestServices(services => {
                services.AddScoped<IStoreRepository, StoreRepositoryTest>();
            });
        }).CreateClient();

        var request = new HttpRequestMessage(new HttpMethod(method), $"{_url}/{code}");

        string readAsStringAsync;

        _output.WriteLine($"Request Uri: {request.RequestUri}");

        using (var response = await client.SendAsync(request)) {
            response.EnsureSuccessStatusCode();
            readAsStringAsync = await response.Content.ReadAsStringAsync();

            if (!response.IsSuccessStatusCode) {
                _output.WriteLine($"Not successful ({response.StatusCode}): {readAsStringAsync}");
            }
        }

        var stores = JsonConvert.DeserializeObject<List<Store>>(readAsStringAsync);

        Assert.True(stores.Any());
    }
}

但是,当我进行测试时,在 Startup.cs 中注册的真实RepositoryStoreRepository 中的断点是被命中的,而不是StoreRepositoryTest 中的断点。我设置我的工厂来覆盖依赖,但它忽略了它。我能做些什么来纠正这个问题。

供参考,我一直在使用这个来源:https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2

更新

不确定这个问题是否应该被删除,但它最终是一个非常愚蠢的错误。我更新了上面的代码以包含一个 using 别名。原来我是在注册和覆盖 V1 接口而不是 V3。当我实现 Mock 类时,我没有意识到我正在实现旧服务。所以好消息是上面的代码是一个如何使用微软文档进行模拟的工作示例。

【问题讨论】:

  • 你是如何运行测试的?
  • 试试builder.ConfigureServices 看看它是否有所作为。注意到同样问题的问题有所增加,而文档确实说要按照您的说明进行操作。
  • @VladimirSerykh 我正在使用 Visual Studio 2019 的测试资源管理器运行测试,我专门使用调试功能来验证代码路径。
  • @Nkosi 通过我的失败,我了解了一些关于它是如何工作的。当我调试和单步执行代码时,我发现 ConfigureServices 是过程中的第一步,然后 ConfigureTestServices 发生。您想使用前者,以便之后注册您的 Mock 服务。我猜微软的 DI 库是最后一个条目。您可以看到原始服务和 Mock 服务都针对同一个接口注册。我不能代表其他人,但我的案例最终是由于将注册与同名的不同服务混淆(V1 与 V3)

标签: c# asp.net-core integration-testing xunit


【解决方案1】:

我以前见过这个。您可能在不同的命名空间中创建了一个接口。

通常,当您拥有用于 Web 服务的版本 1 接口,然后您决定添加新功能时,就会发生这种情况。然后创建一个同名的版本 2 接口。

services.AddScoped&lt;IStoreRepository, StoreRepositoryTest&gt;() 上设置一个断点并对其进行调试。检查结果并滚动到添加服务的底部;您将清楚地了解正在添加的内容。

【讨论】:

  • 就是这样。我一直在努力更新 API 并整合它们,但我不想删除它的旧版本以实现向后兼容性。我在没有意识到的情况下“覆盖”了 V1。我非常专注于这个例子,以至于我没有考虑我正在注册哪个接口。我将更新我的问题以包含一个 using 别名和一个引用它的更新。
【解决方案2】:

1) 您可以尝试使用 CustomWebApplicationFactory 类并在 ConfigureWebHost(IWebHostBuilder builder) 方法中,添加 builder.ConfigureServices(//define dependencies)。 Refer msdn link

2) 或者,您可以定义自己的 TestStartup 类,继承自 Startup 类并使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 2019-04-12
    • 2018-08-04
    • 2011-02-10
    • 1970-01-01
    • 2011-03-15
    相关资源
    最近更新 更多