【问题标题】:How do I use moq to assert a function is called in c#?如何使用 moq 断言在 c# 中调用的函数?
【发布时间】:2012-05-16 02:26:35
【问题描述】:

我正在尝试学习如何使用 Moq 使用 C# 进行单元测试。我设置了一个简单的类,BasicMath,它有一个函数int Multiply(int a, int b),主体只返回a * b。我有另一个名为 AdvancedMath 的类,它有一个函数'int Square(int a)',主体调用 Multiply(a,a) 并返回结果。

我正在尝试为 AdvancedMath.Square 编写一个简单的测试,它将断言使用正确的值调用 BasicMath.Multiply。我知道你不能用普通的公共功能做到这一点,所以我把这些功能设为虚拟,但我仍然遇到麻烦。有人可以向我解释这是如何完成的吗?除了默认的空构造函数之外,这两个类都没有任何构造函数。

这是我的尝试:

class test_Advanced_Functions
{
    [Test]
    public void test_SquareFunction_Should_return_correct_result()
    {
        // Arrange
        Mock<BasicFunctions> mock = new Mock<BasicFunctions>();
        AdvancedFunctions af = new AdvancedFunctions();

        // Act
        int result = af.Square(5);

        //Assert
        mock.Verify(d => d.Multiply(5, 5), Times.Exactly(1));
    }

【问题讨论】:

  • @StriplingWarrior - 不同之处在于所引用的被测方法将另一个类作为其参数之一。应该可以断言调用函数而不强制将对象作为参数传递...对吗?

标签: c# unit-testing moq


【解决方案1】:

假设AdvancedMath 派生自BasicMath,那么当Multiply 是虚拟的时,您可以使用最小起订量对其进行测试:

var mock = new Mock<AdvancedMath>();
mock.Setup(m => m.Multiply(2, 2)).Returns(4);
mock.Object.Square(2);
mock.VerifyAll();

如果您在AdvancedMath 中使用BasicMath(即如果Multiply 是静态的并且直接从Square 调用),那么测试这种交互是不可能的 起订量。要了解原因,请参阅this question

但是,在这种简单的情况下进行基于行为的验证似乎并不正确。您需要回答自己一个问题:“我要测试什么?”Square 有效 还是它调用了一些方法?这个测试(你现在计划做的),只将责任委托给Multiply,假设它有效。您的 Square 实现可能会以多种方式发生变化(例如,不使用 Multiply),它会破坏您的测试 - 它不应该。

【讨论】:

    【解决方案2】:

    Moq 无法修改它尚未创建的实例的行为。

    您应该通过练习依赖注入来编写可单元测试的类。由于AdvancedFunctions 显然依赖于BasicFunctions,它应该有一个BasicFunctions 作为构造函数参数传入,而不是new 自己一个。

    【讨论】:

      猜你喜欢
      • 2014-01-27
      • 1970-01-01
      • 2012-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多