简体   繁体   English

如何使用moq断言在C#中调用的函数?

[英]How do I use moq to assert a function is called in c#?

I am trying to learn how to use Moq to do unit testing with C#. 我正在尝试学习如何使用Moq用C#进行单元测试。 I setup a simple class, BasicMath that has a function int Multiply(int a, int b) , the body just returns a * b. 我设置了一个简单的类BasicMath,它具有一个函数int Multiply(int a, int b) ,主体仅返回a * b。 I have another class called AdvancedMath which has a function 'int Square(int a)', the body calls Multiply(a,a) and returns the result. 我还有另一个叫做AdvancedMath的类,它具有一个函数'int Square(int a)',主体调用Multiply(a,a)并返回结果。

I am trying to write a simple test for AdvancedMath.Square that will assert that BasicMath.Multiply is called with the correct values. 我正在尝试为AdvancedMath.Square编写一个简单的测试,该测试将断言使用正确的值调用BasicMath.Multiply。 I understand that you cannot do this with ordinary public function so I made the functions virtual, but I am still having trouble. 我知道您无法使用普通的公共功能执行此操作,因此我将功能虚拟化,但是仍然遇到麻烦。 Can someone explain to me how this is done? 有人可以向我解释如何完成吗? Neither class has any constructor other than the default empty constructor. 除了默认的空构造函数,这两个类都没有其他构造函数。

Here is my attempt: 这是我的尝试:

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));
    }

Assuming AdvancedMath derives from BasicMath then you can test that with Moq when Multiply is virtual: 假设AdvancedMathBasicMath派生的,那么当Multiply是虚拟的时,您可以使用Moq进行测试:

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

If you use BasicMath within AdvancedMath (ie. if Multiply is static and is invoked directly from Square ), then testing such interaction is not possible with Moq. 如果您在AdvancedMath使用BasicMath (即,如果Multiply是静态的并且直接从Square调用),则无法使用Moq测试这种交互。 To see why, see this question . 要了解原因,请参阅此问题

However, doing behavior based verification in such simple case doesn't seem right. 但是,在这种简单情况下进行基于行为的验证似乎并不正确。 You need to answer yourself a question: "what do I want to test?" 您需要回答一个问题: “我要测试什么?” . That Square works or that it calls some methods? Square 起作用或调用了某些方法? This test (what you plan to do now), only delegates responsibility to Multiply , assuming it works. 假设此测试有效,则此测试(您现在打算做的事情)仅将责任委托给Multiply Your Square implementation might change in multiple ways (as in, not using Multiply ) and it will break your test - it shouldn't. 您的Square实现可能会以多种方式发生变化(例如,不使用Multiply ),它将破坏您的测试-不会。

Moq cannot modify behavior of instances that it has not created. Moq无法修改尚未创建的实例的行为。

You should write your classes to be unit-testable by practicing dependency injection. 您应该通过练习依赖注入来编写可进行单元测试的类。 Since AdvancedFunctions apparently depends on BasicFunctions , it should have a BasicFunctions passed in as a constructor argument, rather than new ing one up on its own. 由于AdvancedFunctions显然取决于BasicFunctions ,它应该有一个BasicFunctions传过来的构造函数的参数,而不是new ING一上来就其自身。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM