繁体   English   中英

如何使用Rhino Mock测试是否调用了类的私有方法?

[英]How can I test if a private method of a class is called or not with rhino mock?

我在C#和Rhino模拟游戏上还很新。 我搜索并找到与我的问题类似的主题,但找不到合适的解决方案。

我试图了解是否在我的单元测试中调用了私有方法。 我正在使用Rhino模拟,阅读了许多有关它的文件,其中一些只是说将方法的访问说明从私有更改为公共,但是我无法更改源代码。 我试图将源文件链接到我的测试项目,但它没有改变。

  public void calculateItems()
    {
        var result = new Result(fileName, ip, localPath, remotePath);

        calculateItems(result, nameOfString);
    }

    private void calculateItems(Result result, string nameOfString )

从上面的代码中可以看到,我有两种方法具有完全相同的名称,calculateItems,但是公共方法没有参数,私有方法有两个参数。 我想了解我在单元测试中何时调用public时,是否调用了private方法?

    private CalculateClass sut;
    private Result result; 

    [SetUp]
    public void Setup()
    {
      result = MockRepository.GenerateStub<Result>();
      sut = new CalculateClass();
    }

    [TearDown]
    public void TearDown()
    {

    }

    [Test]
    public void test()
    {     
        sut.Stub(stub => stub.calculateItems(Arg<Result>.Is.Anything, Arg<string>.Is.Anything));

        sut.calculateItems();

        sut.AssertWasCalled(stub => stub.calculateItems(Arg<Result>.Is.Anything, Arg<string>.Is.Anything));
    }

在我的单元测试中,我遇到了这样的错误:“ computeItems的重载方法不使用两个参数”。 有没有一种方法可以对其进行测试而无需更改源代码?

您正在测试错误的内容。 私有方法是私有的。 它们与使用代码无关,单元测试也与其他代码一样使用代码。

在测试中,您将测试并验证组件的向外功能。 它的内部实现细节与测试无关。 所有测试关心的是被调用的操作是否产生预期的结果。

因此,您必须问自己的问题是...调用此操作时预期的结果是什么?:

calculateItems()

它不返回任何东西,所以它有什么作用 它以某种方式修改到什么状态? 就是您的测试需要观察的内容,而不是实现细节,而是可观察的结果。 (如果操作没有可观察到的结果,则“通过”或“失败”之间没有区别,因此没有要测试的内容。)

我们看不到您的代码的详细信息,但是可观察的结果可能会完全耦合到另一个组件。 如果是这种情况,则其他组件是此操作的依赖项,而单元测试的目标是模拟该依赖项,以便可以独立于依赖项来测试操作。 然后可能需要修改组件,以便提供依赖性而不是内部控制。 (这被称为依赖倒置原则 。)


还要注意...

但我无法更改源代码

这完全是一个单独的问题。 如果您确实无法更改源代码,那么这些测试的价值将大大降低,甚至有可能完全消除。 如果测试失败,您该怎么办? 没有。 因为您无法更改代码。 那么,您正在测试什么?

请记住,对于程序员来说,编写无法进行有意义的单元测试的代码不仅可能而且不幸。 如果此代码是由其他人提供给您的,并且由于某些非技术原因而被禁止更改,那么其他人有责任更正该代码。 “更正”可以包括“使有意义地进行单元测试成为可能”。 (或者说实话, 他们应该对它进行单元测试。不是您。)

如果您的公共方法调用了您的私有方法,那么在您的测试中也会发生同样的事情。 测试不过是可以运行和调试的代码,您可以尝试一下,看看会发生什么。

私有方法不能直接进行测试,但是可以通过公共调用程序进行测试,这就是您正在做的事情,所以这一切都很好。 进行这样的设置是否是一个好主意,完全是另一回事,但我现在不打算讨论。

现在,让我们讨论一下您实际测试的内容。

单元测试不应对测试的代码有深入的了解。 原因是您应该具有输入和输出,并且您不必理会这之间的情况。

如果重构代码并消除私有方法,那么即使您对公共方法的输入和输出保持不变,测试也会中断。 这不是一个好位置,这就是我们所说的脆性测试。

因此,请围绕公共方法添加功能测试,确认您已获得期望,不要担心它是否会调用您的私有方法。

当您需要知道是否调用了私有方法时,可以有两种不同的解释:

  1. 您希望确保在一个特定测试中调用私有方法,从而使其成为该测试的成功标准。

  2. 您想知道是否通过任何测试用例都调用了私有方法。 您可能对此感兴趣,因为您想确定私有方法是否包含在测试套件中,或者如您所说,只是为了了解代码中实际发生的事情。

关于第二种解释:如果您想了解代码中正在发生的事情,一个好的方法是使用调试器,然后单步执行代码以查看调用了什么函数。 因为我不是C#专家,所以我不推荐任何特定的调试工具,但是在Web上找到关于此的一些建议应该并不困难。 这种方法将满足您的要求,而无需更改源代码

另一种可能性,特别是如果您对测试是否涵盖了您的私有功能感兴趣,则是对C#使用测试覆盖率工具。 覆盖率工具将显示是否调用了私有方法。 同样,这不需要对源代码进行任何更改。

关于问题的第一种解释:如果要测试是否调用了某些privat函数作为测试成功标准的一部分,则最好对使用公共API的测试进行此操作。 然后,在这些测试中,由于私有功能对测试结果的影响,您应该能够判断是否调用了私有功能。

并且,与其他意见相反,您应该测试实现。 单元测试的主要目的是发现代码中的错误。 不同的实现有不同的错误。 这就是为什么人们还使用覆盖率工具查看他们是否覆盖了其实现代码的原因。 而且,覆盖范围还不够,您还需要检查表达式的边界情况等。当然,拥有可维护的测试和在重构的情况下不会不必要地破坏的测试是一个好目标(为什么通过公共API进行测试通常是一个好方法-但并非总是如此),但与查找所有错误的目标相比,它们是次要目标。

暂无
暂无

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

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