如何在c#中调用moq来断言函数?

时间:2012-05-07 15:07:32

标签: c# unit-testing moq

我正在尝试学习如何使用Moq使用C#进行单元测试。我设置了一个简单的类BasicMath,它有一个函数int Multiply(int a, int b),正文只返回一个* 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));
    }

2 个答案:

答案 0 :(得分:3)

假设AdvancedMath派生自BasicMath,那么您可以在Multiply为虚拟时使用Moq对其进行测试:

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

如果您在BasicMath内使用AdvancedMath(即如果Multiply是静态的并且直接从Square调用),则测试此类互动 与Moq不可能 。要了解原因,请参阅this question

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

答案 1 :(得分:1)

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

您应该通过练习依赖注入来编写您的类以进行单元测试。由于AdvancedFunctions显然取决于BasicFunctions,因此它应该将BasicFunctions作为构造函数参数传入,而不是new自己的{{1}}。