单元测试:如何从模拟接口异步返回值

时间:2019-01-25 11:38:42

标签: c# unit-testing moq xunit

我正在尝试对方法进行单元测试,并在调用处理HttpClient逻辑的模拟“请求提供程序”时断言结果是特定类型的,尽管我已设置了模拟接口,但它始终返回null。

以前,当使用HttpClient时,我已经模拟了HttpMessageHandler并在另一侧的方法中处理了业务逻辑,但是我们正在使用的第三方API需要使用GET请求多次调用其剩余api,所以我想要一个解决方案使解决方案更加“干燥”

以下是我当前正在尝试使用的设置

_requestProvider.Setup(
    svc => svc.GetAsync<PlayerBalance>(It.IsAny<string>(), It.IsAny<string>()))
    .Returns(() => Task.FromResult(new PlayerBalance
    {
        Balance = 0
    }));

_playerService = new PlayerService(_playerRepository.Object, 
            _secretsService.Object,
            _awsConfig,
            _requestProvider.Object);

我的作为/主张

var result = await _playerService.GetPlayerBalanceAsync(request);

result.Should().BeOfType<PlayerBalance>();

被测方法

public async Task<PlayerBalance> GetPlayerBalanceAsync(PlayerBalanceRequest playerBalanceRequest)
{
    if (string.IsNullOrEmpty(playerBalanceRequest.Login)) throw new Exception("Login is a required parameter.");


    string url = $@"myrestendpoint";

    var result = await _requestProvider.GetAsync<List<PlayerBalance>>(url);

    return result.FirstOrDefault();
}

以及模拟失败的地方

public async Task<TResult> GetAsync<TResult>(string uri, string token = "")
{
    HttpClient httpClient = CreateHttpClient(token);
    HttpResponseMessage response = await httpClient.GetAsync(uri);

    await HandleResponse(response);
    string serialized = await response.Content.ReadAsStringAsync();

    TResult result = await Task.Run(() =>
            JsonConvert.DeserializeObject<TResult>(serialized, _serializerSettings));

        return result;
}

在“严格”状态下运行时,它告诉我它预期调用,但未找到设置。我不确定在这里还需要设置什么。

最后一段代码返回的结果始终为null,但我希望它是PlayerBalance {Balance = 0}

任何帮助将不胜感激。

请澄清一下,我还通过以下方式尝试了设置

.Returns(Task.FromResult(new PlayerBalance
{
    Balance = 0
}));

.ReturnsAsync(new PlayerBalance {
    Balance = 0
});

1 个答案:

答案 0 :(得分:3)

您在嘲笑:

_requestProvider.GetAsync<PlayerBalance>(url)

当你应该嘲笑的时候:

_requestProvider.GetAsync<List<PlayerBalance>>(url)

将模拟程序设置为期望的行为:

_requestProvider.Setup(
        svc => svc.GetAsync<List<PlayerBalance>>(It.IsAny<string>(), It.IsAny<string>())
    )
    .ReturnsAsync(() => new List<PlayerBalance>() { new PlayerBalance
    {
        Balance = 0
    }});