使用Moq,如何使用输入参数设置方法调用作为具有预期属性值的对象?

The*_*ght 34 c# tdd unit-testing moq

使用Moq,如何使用输入参数设置方法调用作为具有预期属性值的对象?

 var storageManager = new Mock<IStorageManager>(); 
 storageManager.Setup(e => e.Add(It.IsAny<UserMetaData>()));
Run Code Online (Sandbox Code Playgroud)

Add()方法需要具有FirstName属性的UserMetaData对象.

我想确保传递了具有FirstName为"FirstName1"的UserMetaData类型的对象.

slo*_*oth 50

你可以用Verify.

例子:

验证Add从未使用UserMetaDatawith FirstName!= 调用"FirstName1":

storageManager.Verify(e => e.Add(It.Is<UserMetaData>(d => d.FirstName!="FirstName1")), Times.Never());
Run Code Online (Sandbox Code Playgroud)

验证是否Add使用UserMetaDatawith FirstName== 至少调用了一次"FirstName1":

storageManager.Verify(e => e.Add(It.Is<UserMetaData>(d => d.FirstName=="FirstName1")), Times.AtLeastOnce());
Run Code Online (Sandbox Code Playgroud)

Add使用FirstName== "Firstname1"LastName== 验证是否只调用了一次"LastName2":

storageManager.Setup(e => e.Add(It.Is<UserMetaData>(data => data.FirstName == "FirstName1"
                                                         && data.LastName  == "LastName2")));

...

storageManager.VerifyAll();
Run Code Online (Sandbox Code Playgroud)

  • 使用`Setup(....)`和`VerifyAll()`或仅使用`Verify`取决于您的个人偏好以及您的用例(您是否使用您使用`Setup`配置的函数的返回值? ,你想指定一个函数应该用`Times`来调用的频率吗?等等) (2认同)

Mat*_*asG 12

您可以使用It.Is方法:

storageManager.Setup(e => e.Add(It.Is<UserMetaData>(data => data.FirstName == "FirstName1")));
Run Code Online (Sandbox Code Playgroud)


And*_*ols 9

Dominic Kexel的方法很好并且可行.您也可以使用回调,但如果您需要检查更复杂的输出,则回调非常有用.

 UserMetaData parameter = null;
 var storageManager = new Mock<IStorageManager>(); 
 storageManager
    .Setup(e => e.Add(It.IsAny<UserMetaData>()))
    .Callback((UserMetaData metaData) => parameter = metaData);

 Assert.That(parameter.FirstName, Is.EqualTo("FirstName1")); //If using fluent NUnit
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,如果需要,您可以对参数进行更多检查,而不仅仅是检查它是否为"FirstName1".

缺点是如果多次调用Add,则只检查最后一次调用中传递的参数(尽管您可以另外验证它是否被调用过一次).

对于你的确切情况,Dominic的答案比我的好,但我想指出其他类似情况的Callback.