模拟Azure MobileServiceClient

时间:2018-11-11 18:45:40

标签: c# unit-testing moq azure-mobile-services

我有一种方法需要进行单元测试,而我只能模拟其中的一部分。

private async void LoginCommandAsync()
    {

        .....

        CancellationToken ct;
        var result = await ClientAuthorizationService.CurrentClient.InvokeApiAsync(Constants.ApiConstants.AzureAuthMeData,
            null, HttpMethod.Get, null, ct);

        ....
    }

我试图使用Moq来模拟Microsoft.WindowsAzure.MobileServices.MobileServiceClient。不幸的是,我总是在最后一行代码中得到System.InvalidCastException

        var currentClient = new Mock<IMobileServiceClient>(MockBehavior.Loose);

        currentClient.Setup(x => x.InvokeApiAsync(Constants.ApiConstants.AzureAuthMeData,
            null, HttpMethod.Get, null, ct)).Returns(Task.FromResult(token));

        var disposableCurrentClient = currentClient.As<IDisposable>();

        ClientAuthorizationService.CurrentClient = (MobileServiceClient)disposableCurrentClient.Object;

MobileServiceClient继承自IDisposable IMobileServiceClient,但无论我如何尝试使用/分配模拟对象,它都无法工作。

public class ClientAuthorizationService : IClientAuthorizationService
{
    public MobileServiceClient CurrentClient { get; set; }
    public ClientAuthorizationService()
    {
        CurrentClient = new MobileServiceClient(Constants.ApiConstants.ApplicationUrl);
    }
} 

1 个答案:

答案 0 :(得分:1)

ClientAuthorizationService.CurrentClient的成员/财产从MobileServiceClient更改为IMobileServiceClient

public interface IClientAuthorizationService  {
    IMobileServiceClient CurrentClient { get; set; }
}

public class ClientAuthorizationService : IClientAuthorizationService {

    public ClientAuthorizationService() {
        CurrentClient = new MobileServiceClient(Constants.ApiConstants.ApplicationUrl);
    }

    public IMobileServiceClient CurrentClient { get; set; }
} 

当测试ClientAuthorizationService现在依赖抽象而不是实现问题时,这将允许分配客户端模拟。

//....

var clientAuthorizationService = new Mock<IClientAuthorizationService>();

var currentClient = new Mock<IMobileServiceClient>();

currentClient
    .Setup(_ => _.InvokeApiAsync(It.IsAny<string>(), null, HttpMethod.Get, null, It.IsAny<CancellationToken>()))
    .ReturnsAsync(token);

clientAuthorizationService
    .Setup(_ => _.CurrentClient)
    .Returns(currentClient.Object);

//.....

此外,建议不要使用async void(事件处理程序除外)

因此,被测代码需要相应地更新。

private async Task LoginCommandAsync() {

    //.....

    CancellationToken ct;
    var result = await ClientAuthorizationService.CurrentClient.InvokeApiAsync(Constants.ApiConstants.AzureAuthMeData,
        null, HttpMethod.Get, null, ct);

    //....
}