我想对我所创建的类进行单元测试,但是这种方法需要先调用另一种方法。例如:
// 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
- 实现以保护成员而不是私有成员,并且我不喜欢必须更改实现的想法为了测试它!
我是否应该使用此解决方案,我的设计中是否存在错误,或者有更聪明的方法吗?
答案 0 :(得分:6)
据我所知,您已经在两种可以使用的方式(使用和不使用运行操作)中测试Stop
。只要mockDevice
正在完成它的工作,在我看来你正在合理地测试它。理想情况下,您应该能够验证发送到设备的命令等(大多数模拟框架都会变得简单)。
答案 1 :(得分:5)
在这种情况下,我个人会对此进行两次测试:
这是该方法中唯一具有不同行为的两个重要用途 - 因此我会对它们进行测试。
编辑: 我明白,为什么你不想在停止之前调用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();
如果无法编译不可能的情况,则无需进行测试。