NSubstitute:模拟方法未返回预期结果

mba*_*i23 2 .net c# unit-testing mocking nsubstitute

一般来说,我对 NSubstitute、模拟和单元测试很陌生。

我试图用来NSubstitute删除我的测试类中的一些依赖项,但是模拟对象中的方法的行为并不像我所期望的那样,基于我如何配置它们。这是我在 Visual Studio 中创建的示例:

  1. 要替换的接口和具体类。注意,MyConcreteClass.MyMethod()返回false

    public interface IMyInterface
    {
        bool MyMethod(string arg);
    }
    
    public class MyConcreteClass : IMyInterface
    {
        public bool MyMethod(string arg)
        {
            return false;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我的测试类:

    public class MyTestedClass
    {
        private IMyInterface _concrete;
    
        public MyTestedClass()
        {
            _concrete = new MyConcreteClass();
        }
    
        public MyTestedClass(IMyInterface mock)
        {
            _concrete = mock;
        }
    
        public bool MyConcreteMethod(string arg)
        {
            return _concrete.MyMethod(arg);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我的单元测试课程MyTestedClass

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void Given_MyMethodIsUsingAMock_ShouldReturnTrue()
        {
            // Arrange
            var myMock = Substitute.For<IMyInterface>();
            myMock.MyMethod("blah").Returns(true);
            var myTestedObject = new MyTestedClass(myMock);
    
            // Act
            var result = myTestedObject.MyConcreteMethod("blah blah");
    
            // Assert
            Assert.AreEqual(result, true); // This assertion fails!
        }
    
        [TestMethod]
        public void Given_MyMethodIsNotMock_ShouldReturnFalse()
        {
            // Arrange
            var myTestedObject = new MyTestedClass();
    
            // Act
            var result = myTestedObject.MyConcreteMethod("blah blah");
    
            // Assert
            Assert.AreEqual(result, false); // This assertion passes.
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 测试结果显示Given_MyMethodIsUsingAMock_ShouldReturnTrue()失败:

    MyUnitTests (2 tests) [0:00.190] Failed: 1 test failed
     MyUnitTests (2 tests) [0:00.190] Failed: 1 test failed
      UnitTest1 (2 tests) [0:00.190] Failed: 1 test failed
       Given_MyMethodIsNotMock_ShouldReturnFalse [0:00.000] Success
       Given_MyMethodIsUsingAMock_ShouldReturnTrue [0:00.189] Failed
    Assert.AreEqual failed. Expected:<False>. Actual:<True>. 
       at MyUnitTests.UnitTest1.Given_MyMethodIsUsingAMock_ShouldReturnTrue() in "c:\MyWorkspace\projects\NSubstituteMocking\MyUnitTests\UnitTest1.cs":line 23
    
    Run Code Online (Sandbox Code Playgroud)

看起来我错过了一个微不足道的配置,但它却在逃避我。

Nko*_*osi 5

安排在给定时MyMethod返回true"blah"

myMock.MyMethod("blah").Returns(true);
Run Code Online (Sandbox Code Playgroud)

但随后"blah blah"在采取行动时提供它。

var result = myTestedObject.MyConcreteMethod("blah blah");
Run Code Online (Sandbox Code Playgroud)

由于预期/安排的参数不匹配,模拟的行为不符合配置。

为模拟提供它期望收到的内容,以使其按预期运行。

[TestMethod]
public void Given_Blah_MyConcreteMethod_ShouldReturnTrue() {
    // Arrange
    var myMock = Substitute.For<IMyInterface>();
    var arg = "blah";
    var expected = true;
    myMock.MyMethod(arg).Returns(expected);
    var myTestedObject = new MyTestedClass(myMock);

    // Act
    var actual = myTestedObject.MyConcreteMethod(arg);

    // Assert
    Assert.AreEqual(expected, actual); // This should pass
}
Run Code Online (Sandbox Code Playgroud)

请注意使用变量来存储提供的值和期望的值,以便在进行测试时可以减少错误。

  • @mbadawi23你可以做 `myMock.MyMethod("").ReturnsForAnyArgs(false)` (参见[文档](http://nsubstitute.github.io/help/return-for-any-args/))。如果您确实需要真实的行为,请考虑使用真实的对象而不是模拟。 (4认同)