我理解单元测试必须尽可能隔离,即自包含,不必依赖外部资源,如数据库,网络访问,甚至执行以前的单元测试。
但是,假设我想测试类Y.Y类使用类X.但是,我已经有许多测试类X的单元测试。
我认为在Y类的单元测试中,我可以假设类X正常工作并使用它的实例来测试类Y(在类Y单元测试中实例化,因此没有剩余物或其他污染)。 / p>
这是对的吗?或者我在测试Y类时是否需要模拟X类或完全做其他事情?如果是这样,或者我应该模仿X类,那是什么原因?
答案 0 :(得分:2)
Y类的单元测试应该只测试Y类的代码。你应该假设Y所依赖的所有东西都已经工作(并经过测试)。这是标准的单元测试。你想减少外部依赖,并尝试隔离你的测试,以便你真的只在Y类的测试中测试Y类的功能,但在现实世界中,一切都是连接的。
在我看来,使用X类并假设它比模拟X类提供更纯粹的单元隔离要好得多。无论哪种方式,你应该假设X类是一个黑盒子并且它可以工作。
答案 1 :(得分:1)
归结为你想要多少纯粹主义者。如果它只是另一个没有依赖外部资源(如数据库等)的类,我就不会发疯并模拟类X. 重要的是您对代码有完整的测试覆盖率。如果已经测试的代码在其他测试中作为“可信代码”运行,则IMO不是问题。
答案 2 :(得分:1)
我会在这里扮演魔鬼的拥护者,并建议除非这是某种类型的集成测试,否则你不要在类Y测试中使用类X,而是使用模拟(甚至是存根)。
我背后的理由是:
如果Y的测试依赖于Y调用X的某些副作用或状态,那么根据定义它不是单元测试。
因此,在Y类的单元测试中,您想要的只是看起来和行为类似于X类,同时完全由测试方法驱动并在其控制之下Y级。
由于假设与单元测试是对立的,如果你想确保在Y测试期间调用X.SomeMethod
时没有任何东西爆炸,那么唯一的方法是100%确定(因此有100对测试的信心百分比)是通过Mock或Stub提供X.SomeMethod
的实现,你可以保证不会失败,因为它什么都不做因此不可能失败。
由于您的类X已经编写并且不包含什么也不做的方法,因此您不能将它用于Y类的单元测试。
要考虑的另一点是如何在使用“真实”类X时模拟失败。你如何提供X到Y,以便X总是导致异常,以便测试Y在面对狡猾的X依赖时如何表现?唯一合理的解决方案是使用X的Mock / Stub。(当然,你可能不会通过单元测试来达到这个级别的细节,所以我只是举一个例子)
考虑当你没有正确进行单元测试的X类更改(测试遗漏,设计测试中的真正错误等)导致异常被抛出时,可能会发生6个月后可能发生的情况在类Y的测试期间调用{1}}。
你怎么能立刻知道问题是X级?或者确实是Y级?你不能,因此失去了隔离单元测试的主要好处。
当然,当您继续进行集成测试时,您将使用类X来测试Y类在生产环境中的行为,但这是一个完全不同的问题......