单元测试一个高抽象级别的方法

Mar*_*cze 3 c# unit-testing mocking

高级单元测试和模拟对象的值已经讨论过类似的主题

但是,我想描述一下具体情况,并询问您对我应该如何编写单元测试的意见.

我正在开发一个使用Entity Framework的普通3层应用程序.在EF之上,我有两层:

  • 存储库:它们直接访问EF ObjectContext并执行所有CRUD工作(实际上,这些类是使用T4模板生成的).所有Repository类都有适当的接口.
  • 管理器:它们实现更高级别的业务逻辑,它们不直接访问ObjectContext,而是使用适当的存储库.管理员不知道具体的Repository实现,只知道接口(我在单元测试中使用依赖注入和模拟).

没有进一步的描述,这里是我想编写单元测试的类:

public class PersonManager
{
    private IPersonRepository personRepository; // This is injected.

    // Constructor for injection is here.

    public void ComplexMethod()
    {
        // High level business logic
        bool result = this.SimpleMethod1();
        if(result)
            this.SimpleMethod2(1);
        else
            this.SimpleMethod2(2);
    }

    public bool SimpleMethod1()
    {
        // Doing some low-level work with the repository.
    }

    public void SimpleMethod2(int param)
    {
        // Doing some low-level work with the repository.
    }
}
Run Code Online (Sandbox Code Playgroud)

单元测试真的很容易,SimpleMethod1SimpleMethod2通过PersonManager模拟实例化PersonRepository.

但我找不到任何方便的单元测试方法ComplexMethod.

你对我该怎么做有什么建议吗?或者根本不应该进行单元测试?也许我不应该使用this方法调用的引用ComplexMethod,而是PersonManager通过接口访问自己,并用mock替换它?

提前感谢任何建议.

Rya*_*art 6

Guillaume的答案很好(+1),但我想再给一个观察.我在你发布的代码中看到的是人们试图弄清(或反对)TDD的一个非常常见的问题的基础,即:

"我应该如何/为什么要测试ComplexMethod(),因为它依赖于SimpleMethod1()和SimpleMethod2(),它们已经过测试并且有自己的行为,我必须在ComplexMethod()的测试中考虑到这一点?我有基本上复制了SimpleMethod1()和SimpleMethod2()的所有测试,以便完全测试ComplexMethod(),这只是愚蠢的."

不久之后,他们通常会发现部分嘲笑.使用部分模拟,您可以模拟SimpleMethod1()和SimpleMethod2(),然后使用常规模拟机制测试ComplexMethod()."听起来不错,"他们认为,"这将彻底解决我的问题!".一个好的模拟框架应该强烈反对以这种方式使用部分模拟,因为现实是:

您的测试告诉您有关设计问题的信息.

具体来说,他们告诉你,你在一个课程中混合了关注点和/或抽象级别.他们告诉你SimpleMethod1()和SimpleMethod2()应该被提取到这个类所依赖的另一个类.无论我看到多少次这种情况,无论开发人员多么激烈地争论,最终都会在100%的时间内证明这些测试是正确的.