更改字段值的 MOQ Mock void 方法

MOQ Mock void method that changes a field value

我是 MOQ 和 Mocking 的新手。
假设我有一个像这样的 class,带有一个更改值的 void 方法:

public class Sample
{
    public virtual int Number { get; set; }

    public virtual void Check(int a)
    {
        this.Number = a > 10 ? this.Number = 100 : this.Number = 200;
    }
}

我想测试 void 方法以确保它正在更改本地字段 Number

[Fact]
public void TestSampleClass()
{
    var sut = new Mock<Sample>();
    sut.Setup(s => s.Number).Returns(50);           

    sut.Setup(s => s.Check(It.IsAny<int>())).Callback(
        (int testNumber) =>
        {
            if (testNumber > 10)
            {
                sut.Setup(s => s.Number).Returns(100);
            }
            else
            {
                sut.Setup(s => s.Number).Returns(200);
            }                   
        });
}

似乎该方法没有将值更改为 100 或 200... 如果我打印 sut.Object.Number 它会给出初始值,而不是 void 调用后的更新值。

Callback 方法只是设置方法的行为,要进行一些更改,您实际上需要调用模拟方法,即 sut.Object.Check(11);,然后您可以断言结果。

除非您的示例是更复杂问题的简化表示,否则无需模拟 Sample class.

[Fact]
public void TestSampleClass()
{
    //Arrange
    var testNumber = 5; //Could be what ever number you want to test
    var expected = 200
    var sut = new Sample();

    //Act
    sut.Check(testNumber);
    var actual = sut.Number;

    //Assert
    Assert.AreEqual(expected, actual);
}

如果目的是学习如何在这种特定情况下执行此类测试,那么您可以这样做...

假设您想在以下接口上测试 Check 方法...

public interface ISample {
    int Number { get; set; }
    void Check(int a);
}

预期的行为是让方法使用 Moq 更改 属性 的值,这就是您可以设置它的方式。

[Fact]
public void TestISampleCheck() {
    //Arrange
    var testNumber = 5; //Could be what ever number you want to test
    var expected = 200;
    var mock = new Mock<ISample>();

    //Specifies that the all properties on the mock should have "property behavior",
    //meaning that setting its value will cause it to be saved and later returned
    //when the property is requested. (this is also known as "stubbing"). The default
    //value for each property will be the one generated as specified by the Moq.Mock.DefaultValue
    //property for the mock.
    mock.SetupAllProperties();

    var sut = mock.Object;

    mock.Setup(s => s.Check(It.IsAny<int>()))
        .Callback((int a) => {
            if (a > 10) {
                sut.Number = 100;
            } else {
                sut.Number = 200;
            }
        });

    //Act
    sut.Check(testNumber);
    var actual = sut.Number;

    //Assert
    Assert.AreEqual(expected, actual);
}