模拟 Azure MobileServiceClient

Mocking Azure MobileServiceClient

我有一个方法需要进行单元测试,但我被其中的模拟部分困住了。

private async void LoginCommandAsync()
    {

        .....

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

        ....
    }

我尝试使用最小起订量模拟 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 继承自 IMobileServiceClient,IDisposable 但无论我如何尝试 use/assign 模拟对象...它都不起作用。

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

ClientAuthorizationService.CurrentClient member/property 从 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);

    //....
}