c# - 如何使用 FakeItEasy 在 .Net Core 中模拟 AsyncPolicyWrap 或 AsyncPolicy

标签 c# .net moq polly fakeiteasy

我有这样的代码(我必须测试一个存储库,您将看到下面的代码)

public class SomeClass
{
    public AsyncPolicyWrap PropName { get; }
    
    public SomeClass(...)
    {     
        PropName = Policy.WrapAsync(someRetry,someCircuitBreaker)
        // here there are passed some methods that return someRetry - AsyncRetryPolicy  
        // and  someCircuitBreaker - AsyncCircuitBreakerPolicy  
    }
}

然后我有另一个 repo 类

public class SomeRepo : ISomeRepo
{
    private readonly AsyncPolicy _somePolicy;
    
    public SomeRepo(..., SomeClass someClass) : base(...)
    {
        _somePolicy = someClass.PropName;
    }
    public async Task<Result<SomeDTO>> GetDTO(Guid someId)
    {
        var someResponse = await _somePolicy.ExecuteAsync(() =>
            HttpClient.GetAsync(serviceName, $"endpointUrl"));
        ...
    }
}

上面的两段代码无法更改,因为它们是在产品中,而我作为初级开发人员只需要在可能的情况下通过测试来覆盖代码

我尝试编写这样的测试

[TestMethod] 
public async Task DoStuff()
{
    var repository = DefaultSome();

    var result = await repository.GetDTO(new Guid());

    result.ShouldNotBeNull(); // don't pay attention I'll change stuff which has to be asserted
}
private SomeRepo DefaultSome(Some some = null) 
{
    some = some ?? A.Fake<ISome>();
    /// HERE I TRIED TO MOCK STUFF IN DIFFERENT WAYS AND I HAVE AN ERROR
    var policyWrap = A.Dummy<AsyncPolicyWrap>();
    //var test = Policy.WrapAsync(A.Fake<AsyncRetryPolicy>(), A.Fake<AsyncCircuitBreakerPolicy>());
    //var test = Policy.WrapAsync(A.Fake<IAsyncPolicy>(), A.Fake<IAsyncPolicy>());

    A.CallTo(() =>
            policyWrap.ExecuteAsync(A<Func<Task<HttpResponseMessage>>>._))
        .Returns(new HttpResponseMessage(HttpStatusCode.OK));

    var policy = A.Fake<RetryPolicies>();
    A.CallTo(() =>
            policy.PropName)
        .Returns(policyWrap);

    return new SomeRepo(some, ..., policy);
}

这是我收到的错误 The error itself

我得到类似的注释//var test = ... variats

最佳答案

具体与抽象

每当你需要模拟某些东西时,就依赖抽象而不是具体的实现。

AsyncPolicyWrap 是一个具体类,而不是 abstract AsyncPolicy

此外,异常表明此类没有公共(public)无参数构造函数。
它有一个 internal有 2 个参数的 ctor:

internal AsyncPolicyWrap(AsyncPolicy outer, IAsyncPolicy inner)
    : base(outer.ExceptionPredicates)
{
    _outer = outer;
    _inner = inner;
}

所以,你应该更喜欢AsyncPolicy abstract类或 IAsyncPolicy 界面。

有或没有结果

请注意,在 Polly 中,每个策略都有两个版本:

  • 不返回任何结果
  • 确实返回一些结果的一个

基于SomeRepo您的策略应返回 HttpResponseMessage 的代码.

所以,你应该使用IAsyncPolicy<HttpResponseMessage>AsyncPolicy<HttpResponseMessage>表明您的保单将返回 HttpResponseMessage .

模拟

每当你 mock IAsyncPolicy<HttpResponseMessage>时那么您不必重新创建组合策略(就像您在评论中所做的那样)。您所要做的就是定义 ExecuteAsync 应该如何表现得好。

幸福之路:

var mockedPolicy = new Mock<IAsyncPolicy<HttpResponseMessage>>();
mockedPolicy
    .Setup(policy => policy.ExecuteAsync(It.IsAny<Func<Task<HttpResponseMessage>>>()))
    .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));

不愉快的道路:

var mockedPolicy = new Mock<IAsyncPolicy<HttpResponseMessage>>();
mockedPolicy
    .Setup(policy => policy.ExecuteAsync(It.IsAny<Func<Task<HttpResponseMessage>>>()))
    .ThrowsAsync(new HttpRequestException("Something bad happened"));

我使用最小起订量来模拟该策略,但相同的概念也可以应用于 FakeItEasy。

关于c# - 如何使用 FakeItEasy 在 .Net Core 中模拟 AsyncPolicyWrap 或 AsyncPolicy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71683824/

相关文章:

c# - 属性的单元测试体

unit-testing - 为什么 AutoFixture 的 AutoMoqData 不创建模拟对象?

c# - Nhibernate 在选择时做更新?

c# - 将凭据发送到 WebBrowser

.net - 如何模拟类的内部方法?

c# - FormsAuthentication.SetAuthCookie 使用最小起订量模拟

asp.net-mvc-3 - 使用 Global.asax 中的代码对自定义 MembershipProvider.ValidateUser 进行单元测试

c# - 处理大量文件

c# - 禁用 Windows Phone 上 ListView 中某些项目的倾斜效果

C#:如何将 HTML5/CSS3 转换为 PDF 文档?