5

试图了解 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

4 回答 4

11

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

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

这是正确的,因为 Act 存在:

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

模拟测试遵循与称为行为验证的非模拟测试不同的模式- 这是我做出的一个答案,它将更加澄清这个概念。

于 2009-07-24T19:48:33.017 回答
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());
于 2009-07-24T19:59:25.507 回答
1

安排:

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

行为:

练习被测代码。

断言:

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

你的问题是你安排然后断言没有在两者之间采取行动。验证系列方法断言你所说的会发生在Setup方法中实际发生了。

于 2009-07-24T19:55:50.633 回答
0

谢谢大家不幸的是,我对这一切都很陌生,并试图快速学习。尤其是术语“行为”“安排”等

所以即使我不明白我在做什么,我还是正确地做到了

newProduct.Object.Name = "乔";

正在制定一项法案。

很棒的解释,非常感谢

最后一件事虽然我认为这些会“设置并采取行动”,但事实并非如此,是吗?你知道两个 SetupProperty 和 SetupSet/Get 之间的区别吗

mock.SetupProperty(f => f.Surname, "foo");

mock.SetupSet(foo => foo.Surname = "foo");

于 2009-07-24T21:18:38.903 回答