【问题标题】:Invoking Func passed as a parameter to a mock using Moq and C#调用 Func 作为参数传递给使用 Moq 和 C# 的模拟
【发布时间】:2012-04-30 05:20:23
【问题描述】:

我有一个看起来像这样的模拟方法:


class NotMineClass {
  T Execute(Func operation) 
  {
    // do something
    return operation();
  }
}

在我的代码中,我这样做:


public MyType MyMethod()
{
  MyType object = new MyType();
  bool success = notMineClassInstance.Execute(() =>
  {
    // some things
    retVal = injectedObject1.method();
    object.attribute = injectedObject2.method();
    // some other things
    return retVal;
  }
  if (success) 
  {
    object.otherAttribute = someValue;
  }
  return object;
}

我的情况是,我正在使用 Moq 测试 MyMethod,并且我想验证 Func 行为是否符合预期。我在它的主体中有一些注入的对象,它们是模拟的,应该被验证;它也开始构建我的返回值,所以除非我调用作为参数传递的函数,否则我不能做任何断言。

在 Java 和 jUnit + EasyMock 中,我会捕获传递的参数,如下所示:


public void testMyMethod() {
  // ...
  Capture < Function < void, Boolean > > functionCapture = Captures.last();
  expect(notMineClassInstance.execute(EasyMock.capture(functionCapture)));
  // Expectations for the body of the function

  replay();

  functionCapture.getValue().apply(null);
}

如何使用 C# + Moq 做同样的事情?

【问题讨论】:

    标签: c# .net moq capture xunit


    【解决方案1】:

    您可以在为方法提供Returns 时捕获调用参数:

    Mock<NotMineClassInstance> mock = new Mock<NotMineClassInstance>();
    mock.Setup(x => x.Execute<bool>(It.IsAny<Func<bool>>()))
        .Returns((Func<bool> captured) => { captured(); return true; });
    

    这是对您的代码的完整测试:

    [Test]
    public void TestingSomething()
    {
        // Arrange
        Mock<NotMineClassInstance> mockNotMine = new Mock<NotMineClassInstance>();
        mockDep.Setup(x => x.Execute<bool>(It.IsAny<Func<bool>>())).Returns((Func<bool> func) => func());
    
        Mock<Injected1> mockInjected1 = new Mock<Injected1>();
        mockInjected1.Setup(i => i.Method()).Returns(true);
    
        Mock<Injected2> mockInjected2 = new Mock<Injected2>();
        mockInjected2.Setup(i => i.Method()).Returns("xxx");
    
        YourClass yourObject = new YourClass(mockDep.Object, mockInjected1.Object, mockInjected2.Object);
    
        // Act
        MyType my = yourObject.MyMethod();    
    
        // Assert
        mockNotMine.Verify(d => d.Execute<bool>(It.IsAny<Func<bool>>()));
        mockInjected1.Verify(i => i.Method());
        mockInjected2.Verify(i => i.Method());
    
        Assert.That(my.Attribute, Is.EqualTo("xxx"));
        Assert.That(my.OtherAttribute, Is.EqualTo(someValue));            
    }
    

    还需要测试 mockInjected1.Method 返回 false 的情况。

    【讨论】:

    • 看起来不错,但是当我这样做时,出现以下错误: Test' failed: System.NullReferenceException : Object reference not set to an instance of an object。在 Test.b__0(Func`1 被捕获)
    • @LuísGuilherme 查看完整的测试样本
    • 从一开始就有效。我在 Func 调用中得到了一个空引用:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多