简体   繁体   中英

Problem mocking delegate with Moq in .Net Core 3.1

I'm having issues mocking a delegate that returns an IHttpClient . This is by requirement of the client, and I cannot change the implementation.

The code looks something like this:

Delegate :

namespace Foo.Http
{
    public delegate IHttpClient FooHttpClientProvider(string name);
}

Test class :

[SetUp]
public void SetUp()
{
    Mock<FooHttpClientProvider>().Setup(x => x("HttpClient")).Returns(Mock<IHttpClient>().Object);
}

When I do this, I get the following exception:

System.InvalidCastException : Unable to cast object of type 'Foo.Http.FooHttpClientProvider' to type 'Moq.IMocked`1[Foo.Http.FooHttpClientProvider]'.

Any ideas? Is this even possible?

Edit: Some extra information: the service I need to test gets injected with a FooHttpClientProvider. We use a global Mock with Autofac that registers the services we need. Since I can't pass the provider as a parameter, I can't instantiate a new Mock for FooHttpClientProvider and pass it to my service as a parameter; I need to set it up in the global mock. This further complicates things.

The code of the service looks something like this:

private readonly FooHttpClientProvider _client;

    public FooService(
        FooHttpClientProvider fooClient)
    {
        
        _client = fooClient("HttpClient");
    }

public async Task<OutputDto> GetAsync(Request request)
{

        var accessToken = await _AuthService.GetAccessTokenAsync();

        try
        {
            var response =
                await ExecuteGet<OutputDto>(
                $"{FooConfig.BaseUrl}someEntpoint{GetQueryParams(request)}", accessToken);
           return response;
        }
        catch(Exception ex)
        {
          //Exception handling
        }
}

The service itself it's working correctly. The problem only arises when trying to mock it for unit testing.

This is most likely an XY problem .

No need to mock the delegate. Use the actual delegate that returns a mock IHttpClient

[SetUp]
public void SetUp() {
    Mock<IHttpClient> clientMock = new Mock<IHttpClient>();
    //... set up the client mock as needed
    
    FooHttpClientProvider provider = (string name) => clientMock.Object;
    

    //... use created delegate as needed
}

I was able to solve this. Turns out that mocking IHttpClient into my global Mock object, that alone was enough to get carried away to my DI container. Worked like a charm.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM