System.Threading.Tasks.Task.Factory.StartNew调用的Moq方法

本文关键字:调用 Moq 方法 StartNew Factory Threading Tasks Task System | 更新日期: 2023-09-27 18:19:51

我正在使用Moq编写单元测试。我有一个DataManager对象,它调用WCF来获取数据。我把这个注入我的控制器。然而,在控制器内部,对该DataManager中的方法的调用被封装在任务内部

System.Threading.Tasks.Task.Factory.StartNew<MyDataObject>(()=>
{
   return DataManager.GetMyDataObject(userobj, recordid);
}

我用Moq为DataManager.GetMyDataObject创建了一个mock但是无论何时从控制器方法内部的该语句调用它则返回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
}

System.Threading.Tasks.Task.Factory.StartNew调用的Moq方法

给定以下类:

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);
}

它在DataManager上调用GetMyDataObject,您必须确保Task在验证模拟设置之前完成。如果您从上面的代码中删除t.Wait();,测试就会失败,因为VerifyAll将在Task启动并调用模拟对象中的GetMyDataObject之前被调用。