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

Moq Method called by System.Threading.Tasks.Task.Factory.StartNew

我正在使用 Moq 编写单元测试。我有一个调用 WCF 来获取数据的 DataManager 对象。我将其注入我的控制器。但是在控制器内部,对该 DataManager 中的方法的调用被包装在 Task

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

我已经为 DataManager.GetMyDataObject 创建了一个带有最小起订量的模拟 但是每当从控制器方法内部的这个语句调用它时 它 return 为空。我在谷歌上搜索了很多,但大部分内容都是处理将 Task 作为 return 签名的方法。

DataManager.GetMyDataObject写成标准同步代码。

我正在使用 Moq v4.0.10827 并且怀疑我是否可以升级。

我正在尝试很多方法..Moq 似乎期望 return 匹配方法签名

_mockDataManager = new Mock<_mockDataManager>();
_mockDataManager.Setup(m => m.GetMyDataObject(It.IsAny<UserObj>(), It.IsAny<Guid>()))

然后 returns?我也试过回调

        _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
}

鉴于以下 类:

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

也许这只是一个 copy/paste 错误,也许不是。

此外,由于您在此处使用 Task

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

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