Moq调用未在模拟上执行

时间:2009-07-24 19:40:04

标签: unit-testing mocking moq

尝试理解verifySet等的使用......但除非我做一个解决方法,否则我无法使用它。

public interface IProduct
{
    int  Id { get; set; }
    string Name { get; set; }
}


public void Can_do_something()
{
    var newProduct = new Mock<IProduct>();
    newProduct.SetupGet(p => p.Id).Returns(1);
    newProduct.SetupGet(p => p.Name).Returns("Jo");

    //This fails!! why is it because I have not invoked it
    newProduct.VerifySet(p => p.Name, Times.AtLeastOnce());

    //if I do this it works
    newProduct.Object.Name = "Jo";
    newProduct.VerifySet(p => p.Name, Times.AtLeastOnce());
 }

有人可以澄清我应该如何在属性上使用VerifySet和Verify和VerifyGet? 我很困惑。

4 个答案:

答案 0 :(得分:10)

您需要在致电验证前执行操作。使用模拟对象的典型单元测试范例是:

// Arrange
// Act
// Assert

所以以下是不正确的用法,因为你错过了你的Act步骤:

public void Can_do_something()
{
    // Arrange
    var newProduct = new Mock<IProduct>();
    newProduct.SetupGet(p => p.Name).Returns("Jo");

    // Act - doesn't exist!
    // Your action against p.Name (ie method call), should occur here

    // Assert
    // This fails because p.Name has not had an action performed against it
    newProduct.VerifySet(p => p.Name, Times.AtLeastOnce());
}

这是正确的,因为法案存在:

public void Can_do_something()
{
    // Arrange
    var newProduct = new Mock<IProduct>();
    newProduct.SetupGet(p => p.Name).Returns("Jo");

    // Act
    LoadProduct(newProduct.Object);

    // Assert
    newProduct.VerifySet(p => p.Name, Times.AtLeastOnce());
}

public static void LoadProduct(IProduct product)
{
    product.Name = "Jo";
}

模拟测试遵循的模式与非模拟测试的模式不同,称为行为验证 - 这是我做的answer,它将更多地阐明这个概念。

答案 1 :(得分:3)

你正在以正确的方式使用VerifySet(),你刚刚从典型的

中省略了// Act阶段
//Arrange

//Act

//Assert

测试施工。正如你的建议,插入

newProduct.Object.Name = "Jo";

进入你的// Act阶段修复了这个问题。

VerifyGet()将以完全相同的方式使用,例如

//Arrange
var newProduct = new Mock<IProduct>();
newProduct.SetupGet(p => p.Id).Returns(1);
newProduct.SetupGet(p => p.Name).Returns("Jo");

//Act
string productName = newProduct.Object.Name;

//Assert
newProduct.VerifyGet(p => p.Name, Times.AtLeastOnce());

newProduct.Verify()用于验证您指定的任何操作,例如

//Arrange
var newProduct = new Mock<IProduct>();
newProduct.SetupGet(p => p.Id).Returns(1);
newProduct.SetupGet(p => p.Name).Returns("Jo");

//Act
newProduct.Object.SomeMethodYouDefineOnTheProductObject();

//Assert
newProduct.Verify(p => p.SomeMethodYouDefineOnTheProductObject(), Times.AtLeastOnce());

答案 2 :(得分:1)

<强>安排:

指示模拟对象在测试期间会发生什么。告诉它将触发哪些事件,将使用哪些方法和属性,以及在这些事情发生时该怎么做。

<强>法

练习测试中的代码。

<强>断言:

询问模拟对象是否告诉他们实际发生的事情。还要检查您的代码,看它是否按预期工作。

你的问题是你安排然后断言而不介入。 Verify系列方法声明您所说的将在Setup方法中实际发生的事情。

答案 3 :(得分:0)

谢谢你们 不幸的是,我是所有这一切的新手,并试图快速学习。特别是术语“行为”“安排”等

所以虽然我不明白我在做什么,但我做得正确

newProduct.Object.Name =“Jo”;

正在制定一项法案。

神奇的解释家伙 非常感谢

最后一件事 我认为这些会“设置并采取行动”,但事实并非如此正确吗? 你知道两个SetupProperty和SetupSet / Get

之间的差异

mock.SetupProperty(f =&gt; f.Surname,“foo”);

mock.SetupSet(foo =&gt; foo.Surname =“foo”);