我有一种方法需要进行单元测试,而我只能模拟其中的一部分。
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);
}
}
答案 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);
//....
}