java - 具有继承和混合的 Scala 可测试代码

标签 java scala unit-testing oop testability

我用 Java 开发了很多代码,并涉足 Groovy 和 Haskell,现在这让我转向了 Scala。

我对 Scala 的功能方面感觉相对舒服,但我发现自己在 Scala 中的面向对象设计方面有点不稳定,因为它感觉与 Java 有点不同,特别是由于特征/混合。

我的目标是编写尽可能可测试的代码,这在我的 Java 开发中一直转化为重点

  • 尽可能保持不变
  • 更喜欢通过构造函数注入(inject)状态
  • 总是寻求组合而不是继承(受 this post on SO 的严重影响,并且可能对其 react 过度)

现在我正试图在这个新的 Scala 领域站稳脚跟,但我很难弄清楚我应该在这里采用什么方法,特别是我是否应该开始对某些东西使用继承目的

Programming Scala(Wampler 和 Payne;O'Reilly,第 2 版)有一节考虑事项(“良好的面向对象设计:题外话”),我读过很多关于 SO 的帖子,但我还没有看到明确提到可测试性的设计考虑。该书提供了有关使用继承的建议:

  1. An abstract base class or trait is subclassed one level by concrete classes, including case classes.
  2. Concrete classes are never subclassed, except for two cases:
    • Classes that mix in other behaviors defined in traits (...)
    • Test-only versions to promote automated unit teting.
  3. When subclassing seems like the right approach, consider partitioning behaviors into traits and mix in those traits instead.
  4. Never split logical state across parent-child type boundaries.

一些关于 SO 的挖掘也表明 sometimes mix-ins are preferable to composition .

所以本质上我有两个问题:

  1. 是否存在使用继承会更好(甚至考虑可测试性)的常见情况?

  2. mix-ins 是否提供了增强代码可测试性的好方法?

最佳答案

您提到的 Q/A 中的特征用法实际上是在处理混合特征所提供的灵 active 。

例如,当您显式扩展特征时,编译器会在编译时锁定类和父类(super class)的类型。在此示例中,MyService 是一个 LockingFlavorA

trait Locking { // ... }

class LockingFlavorA extends Locking { //... }

class MyService extends LockingFlavorA {

}

当您使用类型化的自引用时(如您指向的 Q/A 所示):

class MyService {
   this: Locking =>
}

.. Locking 可以引用 Locking 本身,或 Locking 的任何有效子类。然后,作者在调用站点混合了锁定实现,而没有为此明确创建新类:

val myService: MyService = new MyService with JDK15Locking

我认为当他们说您可以简化测试时,他们实际上是在谈论使用此功能来模拟我们 Java 开发人员通常使用组合和模拟对象所做的事情。您只需制作一个模拟的 Locking 实现并在测试期间将其混合,然后为运行时制作一个真正的实现。

关于您的问题:这比使用模拟库和依赖项注入(inject)好还是坏?这很难说,但我认为最终很大程度上要归结为一种或另一种技术与您的代码库的其余部分配合得如何。

如果您已经在使用组合和依赖项注入(inject)并取得良好效果,我认为继续使用该模式可能是个好主意。

如果您刚刚起步并且还没有真正需要所有这些火炮,或者还没有从哲学上确定依赖注入(inject)适合您,那么您可以从混合中获得很多里程运行时复杂性的成本非常低。

我认为真正的答案将被证明是高度情景化的。

TL; 下面是 DR

问题 1) 我认为它是 composition/dep-inj 的一种在情境下有用的替代方案,但我认为它除了简单之外没有提供任何主要 yield 。

问题 2) 是的,它可以提高可测试性,主要是通过特征实现模拟模拟对象。

关于java - 具有继承和混合的 Scala 可测试代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28517392/

相关文章:

java - 在泛型方法中使用 instanceof

scala - scala中的模式匹配,检查数字是否大于

unit-testing - Windows Store 应用程序的单元测试库中选择的模拟框架是什么?

java - 如何暂停线程执行

Java中的Java编译器

scala - Scala 错误 SI-7914 - 从 Scala 宏返回应用方法是否有任何解决方法?

scala - 如何在 Scala 中转换失败的 future 异常?

typescript 和 Jest : mocking throws typerror because its using the wrong overload

c# - NSubstitute:模拟属性

java - 将 YAML 解析为 JSON 后保留行号