簡體   English   中英

如何使用 FakeItEasy 在 .Net Core 中模擬 AsyncPolicyWrap 或 AsyncPolicy

[英]How to mock AsyncPolicyWrap or AsyncPolicy in .Net Core using 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  
    }
}

然后我有另一個回購協議 class

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"));
        ...
    }
}

上面的 2 段代碼不能更改,因為它們在生產中,我作為初級開發人員只需要盡可能地用測試覆蓋代碼

我試過寫這樣的測試

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

這是我得到的一個錯誤錯誤本身

我得到類似的評論 // var test =... variats

具體與抽象

每當您需要模擬某些東西時,就依賴於抽象而不是具體的實現。

AsyncPolicyWrap是具體的 class 而不是像AsyncPolicy這樣的abstract

同樣作為例外,這個 class 沒有公共無參數構造函數。
它有一個帶有 2 個參數的internal構造函數:

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

因此,您應該更喜歡AsyncPolicy abstract class 或IAsyncPolicy接口。

有或沒有結果

請注意,在 Polly 中,每個策略都有兩個版本:

  • 一個不返回任何結果的
  • 一個確實返回一些結果的

根據SomeRepo的代碼,您的策略應該返回一個HttpResponseMessage

因此,您應該使用IAsyncPolicy<HttpResponseMessage>AsyncPolicy<HttpResponseMessage>來指示您的策略將返回HttpResponseMessage

Mocking

每當您模擬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。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM