C# 如何使用rhino mock测试类的私有方法是否被调用?

C# 如何使用rhino mock测试类的私有方法是否被调用?,c#,unit-testing,private-class,C#,Unit Testing,Private Class,我对C#和犀牛模仿很陌生。我搜索并找到了与我的问题类似的主题,但找不到合适的解决方案 我试图理解在我的单元测试中是否调用了私有方法。我正在使用rhino mock,读了很多关于它的文件,其中一些只是说将方法的访问说明符从private更改为public,但我无法更改源代码。我试图将源文件链接到我的测试项目,但它没有改变 public void calculateItems() { var result = new Result(fileName, ip, localP

我对C#和犀牛模仿很陌生。我搜索并找到了与我的问题类似的主题,但找不到合适的解决方案

我试图理解在我的单元测试中是否调用了私有方法。我正在使用rhino mock,读了很多关于它的文件,其中一些只是说将方法的访问说明符从private更改为public,但我无法更改源代码。我试图将源文件链接到我的测试项目,但它没有改变

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

        calculateItems(result, nameOfString);
    }

    private void calculateItems(Result result, string nameOfString )
正如您从上面的代码中看到的,我有两个方法具有完全相同的名称calculateItems,但公共方法没有参数,私有方法有两个参数。我试图理解当我在unittest中调用公共方法时,是否调用了私有方法

    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));
    }
私有计算类sut;
私人结果;
[设置]
公共作废设置()
{
结果=MockRepository.GenerateStub();
sut=新的CalculateClass();
}
[撕裂]
公共无效拆卸()
{
}
[测试]
公开无效测试()
{     
sut.Stub(Stub=>Stub.calculateItems(Arg.Is.Anything,Arg.Is.Anything));
sut.calculateItems();
调用sut.assertwas(stub=>stub.calculateItems(Arg.Is.Anything,Arg.Is.Anything));
}

在我的单元测试中,我犯了这样一个错误,它说“没有用于计算的重载方法项接受两个参数”。有没有一种方法可以在不改变源代码的情况下测试它?

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

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

所以你必须问自己的问题是。。。调用此操作时的预期结果是什么

calculateItems()
它不返回任何东西,那么它做什么呢?它以某种方式修改了什么状态?这是您的测试需要观察的,不是实现细节,而是可观察的结果。(如果操作没有可观察的结果,那么“通过”和“失败”之间没有区别,因此没有什么可测试的。)

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


同样值得注意的是

但是我不能更改源代码

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


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

你在测试错误的东西。私有方法是私有的。它们与使用代码无关,单元测试也像其他测试一样使用代码

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

所以你必须问自己的问题是。。。调用此操作时的预期结果是什么

calculateItems()
它不返回任何东西,那么它做什么呢?它以某种方式修改了什么状态?这是您的测试需要观察的,不是实现细节,而是可观察的结果。(如果操作没有可观察的结果,那么“通过”和“失败”之间没有区别,因此没有什么可测试的。)

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


同样值得注意的是

但是我不能更改源代码

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


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

如果你的公共方法调用你的私有方法,那么同样的事情也会发生在你的测试中。测试只不过是可以运行和删除的代码