我有一个使用基于任务的异步功能与WCF服务交互的Web应用程序。当我写一个单元测试时遇到了一个关于模拟异步函数调用的问题。我认为不需要显示不必要的业务逻辑,因为所有这些都只在这些异步调用上失败。我试图用两种方式做到这一点,第一种方式是:
[TestMethod]
public async Task GetAndSentSentinelList_AddedTest()
{
var mockRemoteClient = new Mock<IRemoteManager>();
mockRemoteClient.Setup(method => method.GetSentinelListAsync(new GetSentinelListRequest()))
.Returns(Task.FromResult(new GetSentinelListResponse(new RemoteManager.SentinelItem[4]
{
new RemoteManager.Item() {Id = "Identity_Host"},
new RemoteManager.Item() {Id = "Nose_Host"},
new RemoteManager.Item() {Id = "Sunny_Host"},
new RemoteManager.Item() {Id = "Ups_Supsu"}
})));
var rep = new Repository(hub)
{
Client = mockRemoteClient.Object,
Sentinels = new List<SentinelItem>()
{
new Item() {Id = "Identity_Host"},
new Item() {Id = "Nose_Host"},
new Item() {Id = "Sunny_Host"}
}
};
var res = await rep.Client.GetSentinelListAsync(new GetSentinelListRequest());
//Assert
Assert.IsNotNull(res );
}
接下来是:
[TestMethod]
public async Task GetAndSentSentinelList_AddedTest()
{
//Arrange
var tcs = new TaskCompletionSource<GetSentinelListResponse>();
var expectedResult = new GetSentinelListResponse(new RemoteManager.SentinelItem[4]
{
new RemoteManager.Item() {Id = "Identity_Host"},
new RemoteManager.Item() {Id = "Nose_Host"},
new RemoteManager.Item() {Id = "Sunny_Host"},
new RemoteManager.Item() {Id = "Ups_Supsu"}
});
tcs.SetResult(expectedResult);
var mockRemoteClient = new Mock<IRemoteManager>();
mockRemoteClient.Setup(method => method.GetSentinelListAsync(new GetSentinelListRequest()))
.Returns(tcs.Task);
var rep = new Repository(hub)
{
Client = mockRemoteClient.Object,
Sentinels = new List<SentinelItem>()
{
new Item() {Id = "Identity_Host"},
new Item() {Id = "Nose_Host"},
new Item() {Id = "Sunny_Host"}
}
};
var res = await rep.Client.GetSentinelListAsync(new GetSentinelListRequest());
Assert.IsNotNull();
}
也许我会添加生成的代码,因为我现在很困惑为什么它不能正常工作,生成抽象接口IRemoteManager:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="RemoteManager.IRemoteManager", CallbackContract=typeof(Web_Manager.RemoteManager.IRemoteManagerCallback))]
public interface IRemoteManager
{
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IRemoteManager/GetSentinelList", ReplyAction="http://tempuri.org/IRemoteManager/GetSentinelListResponse")]
System.Threading.Tasks.Task<Web_Manager.RemoteManager.GetSentinelListResponse> GetSentinelListAsync(Web_Manager.RemoteManager.GetSentinelListRequest request);
}
具体生成的IRemoteManager实现, - RemoteManagerClient:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class RemoteManagerClient : System.ServiceModel.DuplexClientBase<Web_Manager.RemoteManager.IRemoteManager>, Web_Manager.RemoteManager.IRemoteManager {
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<Web_Manager.RemoteManager.GetSentinelListResponse> Web_Manager.RemoteManager.IRemoteManager.GetSentinelListAsync(Web_Manager.RemoteManager.GetSentinelListRequest request) {
return base.Channel.GetSentinelListAsync(request);
}
}
答案 0 :(得分:1)
我对Moq并不熟悉,但您可以尝试的一件事是在设置模拟时以及调用它时传递相同的SentinelListRequest
。
[TestMethod]
public async Task GetAndSentSentinelList_AddedTest()
{
var sentinelRequest = new GetSentinelListRequest();
var mockRemoteClient = new Mock<IRemoteManager>();
mockRemoteClient.Setup(method => method.GetSentinelListAsync(sentinelRequest))
.Returns(Task.FromResult(new GetSentinelListResponse(new RemoteManager.SentinelItem[4]
{
new RemoteManager.Item() {Id = "Identity_Host"},
new RemoteManager.Item() {Id = "Nose_Host"},
new RemoteManager.Item() {Id = "Sunny_Host"},
new RemoteManager.Item() {Id = "Ups_Supsu"}
})));
var rep = new Repository(hub)
{
Client = mockRemoteClient.Object,
Sentinels = new List<SentinelItem>()
{
new Item() {Id = "Identity_Host"},
new Item() {Id = "Nose_Host"},
new Item() {Id = "Sunny_Host"}
}
};
var res = await rep.Client.GetSentinelListAsync(sentinelRequest);
//Assert
Assert.IsNotNull(res );
}
另一种选择可能是使用类似this
的内容来指定忽略调用的参数mockRemoteClient.Setup(method => method.GetSentinelListAsync(It.IsAny<SentinelGetRequest>()))
.Returns(Task.FromResult(new GetSentinelListResponse(new RemoteManager.SentinelItem[4]
{
new RemoteManager.Item() {Id = "Identity_Host"},
new RemoteManager.Item() {Id = "Nose_Host"},
new RemoteManager.Item() {Id = "Sunny_Host"},
new RemoteManager.Item() {Id = "Ups_Supsu"}
})));