我正在使用Moq编写单元测试。我有一个DataManager对象,它调用WCF来获取数据。我把它注入我的控制器。但是在控制器内部,对此DataManager中的Method的调用将包含在Task
中System.Threading.Tasks.Task.Factory.StartNew<MyDataObject>(()=>
{
return DataManager.GetMyDataObject(userobj, recordid);
}
我用Moq为DataManager.GetMyDataObject创建了一个模拟器 但每当从控制器方法内部的这个语句中调用它 它返回null。我用谷歌搜索了很多,但大多数东西都在处理将Task作为返回签名的方法。
DataManager.GetMyDataObject被写为标准同步代码。
我正在使用Moq v4.0.10827并怀疑我可以升级。
我正在尝试很多方法.Moq似乎期望返回匹配方法签名
_mockDataManager = new Mock<_mockDataManager>();
_mockDataManager.Setup(m => m.GetMyDataObject(It.IsAny<UserObj>(), It.IsAny<Guid>()))
然后返回?我也是trid回调
_mockDataManager.Setup(m => System.Threading.Tasks.Task.FromResult(m.GetMyDataObject(It.IsAny<UserObj>(), It.IsAny<Guid>())
.Returns(System.Threading.Tasks.Task.FromResult(myData))
.Callback<MyDataObject>(o => myData = o);
myData = GetMyDataObject();
_mockDataManager.Setup(m => m.GetMyDataObject(It.IsAny<UserObj>(), It.IsAny<Guid>()).Returns(GetMyDataObject())
private GetMyDataObject() {
returns new DataSet(); //basically an empty dataset but not null
}
答案 0 :(得分:1)
鉴于以下类别:
public class MyDataObject { }
public class UserObj { }
public class DataManager
{
public virtual MyDataObject GetMyDataObject(UserObj userObj, Guid guid)
{
throw new NotImplementedException();
}
}
class SUT
{
public DataManager DataManager { get; private set; }
public SUT(DataManager dataManager)
{
DataManager = dataManager;
}
public void Method(UserObj userobj, Guid recordid)
{
var t = System.Threading.Tasks.Task.Factory.StartNew<MyDataObject>(()=>
{
return DataManager.GetMyDataObject(userobj, recordid);
});
t.Wait();
}
}
以下模拟工作正常:
var mockDataManager = new Mock<DataManager>();
mockDataManager.Setup(m => m.GetMyDataObject(It.IsAny<UserObj>(), It.IsAny<Guid>()));
var sut = new SUT(mockDataManager.Object);
sut.Method(new UserObj(), Guid.Empty);
mockDataManager.VerifyAll();
两个陷阱:
在您发布的代码中,您使用
_mockDataManager = new Mock<_mockDataManager>();
应该是
_mockDataManager = new Mock<DataManager>(); // or whatever the name of the class is
也许这只是一个复制/粘贴错误,也许不是。
此外,由于您在此处使用Task
:
System.Threading.Tasks.Task.Factory.StartNew<MyDataObject>(()=>
{
return DataManager.GetMyDataObject(userobj, recordid);
}
在GetMyDataObject
上调用DataManager
,您必须确保在之前Task
完成验证您的模拟设置。如果您要从我上面的代码中删除t.Wait();
,则测试会失败,因为VerifyAll
会在Task
启动之前调用,并在模拟对象中调用GetMyDataObject
。