N 受保护方法的替代品

问题描述 投票:0回答:1

我正在将现有的单元测试从 Moq 迁移到 NSubstitute

对于大多数情况,这是一个非常平滑的过渡,但是当涉及到模拟HttpMessageHandlerSendAsync)时,有一种非常巧妙的方法可以进入moq上的私有方法。

(前面的最小起订量示例,用于设置带有参数表达式的返回)

protected void SetupHandler<T>(Expression<Func<HttpRequestMessage, bool>> match, HttpStatusCode httpStatusCode,
   T body)
    {
        SetupHandlerStringResponse(match, httpStatusCode, JsonConvert.SerializeObject(
            body), "application/json");
    }

    protected void SetupHandlerStringResponse(Expression<Func<HttpRequestMessage, bool>> match, HttpStatusCode httpStatusCode,
string body, string contentType)
    {
        MockHttpMessageHandler.Protected()
            .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is(match), ItExpr.IsAny<CancellationToken>())
            .ReturnsAsync(new HttpResponseMessage
            {
                StatusCode = httpStatusCode,
                Content = new StringContent(body, Encoding.UTF8, contentType)
            });
    }

    protected void VerifyHandler(Expression<Func<HttpRequestMessage, bool>> match, Times times)
    {
        MockHttpMessageHandler.Protected().Verify("SendAsync", times, ItExpr.Is(match), ItExpr.IsAny<CancellationToken>());
    }

使用SetupHandler和VerifyHandler我可以轻松地在我的代码中调用设置/验证步骤,如下所示...

SetupHandler(t => t.Method == HttpMethod.Get, HttpStatusCode.OK, lookup);

var response = await Class.DoSomething();

Assert.NotNull(response);

VerifyHandler(t => t.Method == HttpMethod.Get && t.RequestUri.PathAndQuery == $"/api/endpointName", Times.Once());

据我所知,NSubstitute 中没有直接案例支持这一点。

我在网上发现了很多关于此类问题的文章,而且似乎总是存在某种参数问题。我已经多次看到这种方法弹出来替换这个“受保护”访问器

这种方式如果没有参数或不需要参数验证似乎可以工作

但就我而言,如果我无法使用 Arg.Is 表达式来验证输入并仍然模拟 HttpMessageHandler 的输出,那么它对我来说没有用。

任何帮助/想法将不胜感激。

c# .net-core moq nsubstitute
1个回答
0
投票

我想我为自己的问题找到了可以接受的答案。

找到了Daniel Ward(罐头中的丹)的[THIS][1]文章,其中概述了 3 个潜在的解决方案。

选项 1:创建一个假的 HttpMessageHandler 类 这对我来说并不是真的,我仍然需要能够使用 NSubstitute 来匹配输入的响应。

选项 2:使用扩展方法中的反射设置对受保护的 SendAsync() 方法的调用 这正是我正在寻找的。正确插入后,它似乎拥有我用最小起订量替换当前设置所需的一切

选项 3:来自 RichardSzalay.MockHttp 的 MockHttpMessageHandler 这个选项也有效,而且看起来效果非常好。但避免了这一点,只是为了向解决方案引入一个新的包。

希望将我的示例指向本文对以后的人有所帮助,甚至更乐观的是,NSubstitute 在库中引入了类似的内容,因此它会像在 Moq 中一样出现在 .Protected() 中。 [1]: https://daninacan.com/how-to-mock-httpclient-in-c-using-nsubstitute-3-ways/

© www.soinside.com 2019 - 2024. All rights reserved.