3

I have an application that currently works as designed, but I am trying to setup integration testing with xUnit before I expand upon it. At the moment the test will only use the original service when performing the test and I don't see why.

This the is the test:

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

However when I conduct the test the break point in the real Repository, StoreRepository that is registered in Startup.cs is the one that is hit, not the break point in StoreRepositoryTest. I setup my factory to override the dependency, but it's ignoring it. What can I do to correct this.

For reference, I have been using this source: https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2

Update

Not sure if this question should be deleted or not but it ended up being a really silly mistake. I updated the code above to include a using alias. It turned out I was registering and overriding the V1 interface instead of V3. When I implemented the Mock class I didn't realize I was implementing the old service. So the good news is the above code is a working example of how to mock using Microsoft's documentation.

Jeff
  • 1,727
  • 2
  • 17
  • 29
  • How exactly do you run the test? – Vlad DX Aug 22 '19 at 21:16
  • Try with `builder.ConfigureServices` and see if it makes a difference. Noticing an uptick in question with this same problem while the docs do say to do as you have shown. – Nkosi Aug 22 '19 at 22:27
  • @VladimirSerykh I'm using Visual Studio 2019's test explorer to run the test, and I specifically use the debug feature to verify the code path. – Jeff Aug 23 '19 at 02:48
  • @Nkosi Through my failure I learned a bit about how this works. When I was debugging and stepping through the code I found that ConfigureServices is kind of a step one in the process, and ConfigureTestServices happens afterwards. You want to use former so your Mock services are registered afterwards. I guess Microsoft's DI library takes the last entry. You can see that both the original and Mock services are registered against the same Interface. I can't speak for the others but my case ended up being due to confusing the registration with a different service of the same name (V1 versus V3) – Jeff Aug 23 '19 at 19:22

2 Answers2

3

I have seen this before. You probably created an interface in a different namespace.

Typically, this happens when you have a version 1 interface for a web service, and then you decide to add new functionality. You then create a version 2 interface with exactly the same name.

Put a break point on services.AddScoped<IStoreRepository, StoreRepositoryTest>() and debug that. Inspect the results and scroll to the bottom where your services are being added; You’ll get a clear view of what’s being added.

ThePeter
  • 883
  • 1
  • 7
  • 15
  • This was exactly it. I've been working on updating API's and consolidating them but I didn't want to remove the older version of it for backwards compatibility. I was "overriding" V1 without realizing it. I was so focused on the example that I wasn't thinking about which Interface I was registering. I'll update my question to include a using alias with an update referring to it. – Jeff Aug 23 '19 at 17:53
0

1) You can try using CustomWebApplicationFactory class and in ConfigureWebHost(IWebHostBuilder builder) method, add builder.ConfigureServices(//define dependencies). Refer msdn link

2) Alternatively, you can define your own TestStartup class inheriting from Startup class and use it.

Bob Ash
  • 837
  • 9
  • 11