我开始在我的项目中实践 TDD,作为背景,它还包含遗留代码。我们使用 Mockito 作为模拟框架并遵循 Spring MVC 方法。
有时,Service
类使用许多不同的 DAO
对象作为 @Autowired
属性实现。这些服务中有一些简单的方法,例如 completeTransaction
。
completeTransaction
将使用许多 DAO
对象来完成其职责
- 更新并保存交易
- 推进业务流程
- 关闭其他未决操作
但是,在执行这些操作时,该方法需要调用不同的 DAO
来获取和更新事务、获取业务流程 ID、获取挂起的事务(并保存它们的更新)。这意味着对该方法进行单元测试会让我添加许多 @Mock
属性。我需要在测试实际完成之前设置模拟对象,以便我测试特定条件。
这似乎是一种代码味道,对我来说,这几乎感觉就像是测试在确保代码的实现而不仅仅是它的契约。同样,如果不模拟依赖项,测试用例将不会运行(由于 NPE 和其他原因)。
我可以遵循什么策略来清理这样的代码? (尽管我无法真正提供有关该问题的实际源代码)。我认为一种可能性是使用(“getPendingOperations”和“advanceBusinessProcess”)之类的方法设置外观类。然后我可以模拟一个依赖项。但后来我发现,在所有其他有这种情况的类中,我需要做同样的事情,然后我害怕为了更清晰的测试而结束很多“帮助”类。
先谢谢你。
最佳答案
我认为当您发现自己有太多模拟时,通常会想做两件事。这些内容不一定简单,但您可能会发现它们很有帮助。
1) 尝试使您的方法和类更小。我认为 Clean Code 说有两条规则,即类应该小。那个类应该比那个小。这是有道理的,因为随着您测试的单元(方法和类)变小,依赖项也会变小。当然,您最终会进行更多测试,但每次测试的设置会更少。
2) 查看得墨忒耳法则 (https://en.wikipedia.org/wiki/Law_of_Demeter)。有很多规则,但基本上,您希望避免长串的属性/方法调用。 objA = objB.propertyA.SomeMethod().propertyC;
如果您需要模拟所有这些对象只是为了获得 objA,那么您将需要进行大量设置。但是,如果您可以用 objA = objB.newProperty;
替换它,那么您只需要模拟 objB 并且它是一个属性。
这些都不是 Elixir ,但希望您可以在您的项目中使用其中的一些想法。
关于java - 单元测试和太多模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21238474/