使用 Moq `It.Is` 验证具有私有字段的构造函数参数/对象

Mis*_*tyK 5 c# moq

非常简单的例子:

public class Test
{
     private int _field;

   public Test(int field)
   {
     _field = field;
   }
}
Run Code Online (Sandbox Code Playgroud)

现在我想检查是否使用 Test 类型的参数调用方法,该方法的构造函数参数等于 5

_mock.Verify(x => x.Method(It.Is<Test>(constructor parameter equal to 5)));
Run Code Online (Sandbox Code Playgroud)

Stu*_*tLC 3

如果我理解正确的话,您有一个 SUT(SystemUnderTest如下所示),它调用一个依赖项( ) ,您已经用不公开公共 getter 属性IDependency的类()的对象模拟了该依赖项。Test就目前而言,您需要使用类似反射的黑客来检查私有值,例如:

  public static TReturn GetPrivateField<TIn,TReturn>(TIn instance, 
                                                     string fieldName)
  {
     var fieldInfo = typeof(TIn).GetField(fieldName, BindingFlags.NonPublic | 
                             BindingFlags.Instance);
     return (fieldInfo != null)
               ? (TReturn)fieldInfo.GetValue(instance)
               : default(TReturn);
  }

  [Test]
  public void EnsureMethod()
  {
     var mock = new Mock<IDependency>();
     var sut = new SystemUnderTest(mock.Object);
     sut.DoSomethingGoodWithTest();

     mock.Verify(x => x.Method(It.Is<Test>(
                     t => GetPrivateField<Test, int>(t, "_field") == 5)));
  }
Run Code Online (Sandbox Code Playgroud)

显然这远非理想,如果可能的话,可以重新考虑该方法:

如果您无法使用Test._field公共 getter 来更改访问可见性,但能够更改正在测试的类的设计,则另一种选择是使用可注入工厂来创建Test类,例如使用类似的方法IFactory.Create(int x)。这样,您可以在测试期间模拟工厂,然后拦截 Create 调用并验证 SUT 确实Test使用所需的构造参数创建对象。