单元测试依赖方法

时间:2009-03-09 08:57:42

标签: c# unit-testing

我想对我所创建的类进行单元测试,但是这种方法需要先调用另一种方法。例如:

// This would work
MyClass myClass1 = new MyClass(mockDevice);
myClass1.Run(myDatastructure);
myClass1.Stop();

// This would throw an InvalidOperationException
MyClass myClass2 = new MyClass(mockDevice);
myClass2.Stop();

Run正在硬件设备上启动操作,Stop当然是在尝试停止该操作(发送reset-command并启动超时定时器)。

无论如何,我想测试调用Stop的各种后置条件,但我不想调用Run,因为我正在测试Stop - 而不是{{1 }}!我想要这样的东西:

Run

到目前为止,我只看到一个可能的解决方案,那就是创建一个继承自MyClass myClass = new MyClass(mockDevice); myClass.Stop(); Assert.IsTrue(mockDevice.ResetCalled); 的{​​{1}},这样就可以设置TestableMyClass实例的正确内部状态在致电MyClass之前。这个解决方案的问题是我必须更改我的MyClass - 实现以保护成员而不是私有成员,并且我喜欢必须更改实现的想法为了测试它!

我是否应该使用此解决方案,我的设计中是否存在错误,或者有更聪明的方法吗?

3 个答案:

答案 0 :(得分:6)

据我所知,您已经在两种可以使用的方式(使用和不使用运行操作)中测试Stop。只要mockDevice正在完成它的工作,在我看来你正在合理地测试它。理想情况下,您应该能够验证发送到设备的命令等(大多数模拟框架都会变得简单)。

答案 1 :(得分:5)

在这种情况下,我个人会对此进行两次测试:

  1. 首先调用没有Run()的测试。我会测试它是否真的抛出异常。我还会测试后期条件是否符合我的期望。
  2. 首先调用Run()进行测试。我只会测试我期望的后期条件。
  3. 这是该方法中唯一具有不同行为的两个重要用途 - 因此我会对它们进行测试。

    编辑: 我明白,为什么你不想在停止之前调用run-你认为如果运行失败,那么应该只测试stop方法的测试很可能也会失败。

    但是,我认为你还测试了run方法。这意味着,当测试时,测试run方法传递 - 停止方法测试的行为也必须通过。如果run方法测试失败,那么run方法测试的结果是未定义的 - 它们可能会也可能不会失败。

    所以,我会说,不要害怕在测试中调用其他依赖方法,但要确保在单独的测试中测试这些依赖方法。

答案 2 :(得分:1)

它不会对你的直接问题有所帮助,但我倾向于将状态映射到类型,而不是让对象具有不同的模式。

IdleDevice idle = new IdleDevice(mockDevice);
RunningDevice running = idle.Run(myDatastructure);
running.Stop();

// This would not compile, as IdleDevice has no Stop method
IdleDevice idle = new IdleDevice(mockDevice);
idle.Stop();

如果无法编译不可能的情况,则无需进行测试。