【问题标题】:Problem mocking delegate with Moq in .Net Core 3.1在 .Net Core 3.1 中使用 Moq 模拟委托的问题
【发布时间】:2022-01-05 01:59:25
【问题描述】:

我在模拟返回 IHttpClient 的委托时遇到问题。这是客户的要求,我无法更改实现。

代码如下所示:

代表

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

测试类

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

当我这样做时,我得到以下异常:

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

有什么想法吗?这甚至可能吗?

编辑: 一些额外信息:我需要测试的服务被注入了 FooHttpClientProvider。我们使用带有 Autofac 的全局 Mock 来注册我们需要的服务。由于我无法将提供程序作为参数传递,因此我无法为 FooHttpClientProvider 实例化新的 Mock 并将其作为参数传递给我的服务;我需要在全局模拟中设置它。这使事情变得更加复杂。

服务的代码如下所示:

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

服务本身运行正常。只有在尝试模拟它进行单元测试时才会出现问题。

【问题讨论】:

    标签: c# .net unit-testing asp.net-core mocking


    【解决方案1】:

    这很可能是XY problem

    无需模拟委托。使用返回模拟IHttpClient的实际委托

    [SetUp]
    public void SetUp() {
        Mock<IHttpClient> clientMock = new Mock<IHttpClient>();
        //... set up the client mock to behave as needed
        
        FooHttpClientProvider provider = (string name) => clientMock.Object;
        
    
        //... use created delegate as needed with the subject under test
        FooService subject = new FooService(provider);
    }
    

    调用主体构造函数的位置

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

    在测试中创建的委托将调用并返回模拟的IHttpClient

    【讨论】:

    • 感谢您的回答。问题在于我需要测试的服务被注入了 FooHttpClientProvider。我们使用带有 Autofac 的全局 Mock 来注册我们需要的服务。由于我无法将提供程序作为参数传递,因此我认为我无法按照您的建议进行设置。除非我误解了你的回答。
    • @waching 使用与您上次评论相关的详细信息和代码更新您发布的问题。然后可以使用该信息提供正确的答案。
    • 完成,谢谢。
    • @waching,被测对象的代码在哪里?
    • 已添加服务代码。
    【解决方案2】:

    我能够解决这个问题。事实证明,将 IHttpClient 模拟到我的全局 Mock 对象中,仅此一项就足以让我进入我的 DI 容器。像魅力一样工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-11
      • 2011-04-24
      • 2020-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多