scala特征 - 关于测试和界面污染的问题

时间:2014-04-02 20:15:07

标签: scala unit-testing traits

几周前我开始使用Scala。总的来说,我非常喜欢这种语言为开发人员提供的所有功能,但有时很难从Java习惯转换。

这个问题与特质有关。目前几乎每次我都会看到我将提取到Java中不同类的逻辑的一部分,并将构造函数参数添加到依赖类我转而创建特征并将其混合到我的类中。 (如果你只有一把锤子,一切看起来像钉子)

但我发现我的方法存在两个问题。

测试具有混合特征的类:

Java如果我有class Foo使用BarBaz类,我可能会将它们注入我的Foo课程并使用它们。如果我使用特征这样做,我将class Foo extends Bar with Baz

现在在我的测试中,我必须编写类似

的内容
trait BarMock extends Bar{
    override def bar = "barMock"
}

trait BazMock extends Baz{
    override def baz = "bazMock"
}

val foo = new Foo with BarMock with BazMock

如果我想交换一些特质行为的实现。也许只是我用来写作

Bar bar = mock(Bar.class);
when(bar.bar()).thenReturn("barMock");
Baz baz = mock(Baz.class);
when(baz.baz()).thenReturn("bazMock");
Foo foo = new Foo(bar, baz);

我在Scala项目中展示的模拟特征是否正常?或者我应该限制自己在测试中混淆嘲弄的特征。

特质方法可见性

这也与我目前对特质的痴迷有关。在Java中,如果我将Bar, Baz实例注入Foo实例,我不会自动将Bar, Baz中的所有公共方法添加到Foo接口。如果我想这样做,我必须手工添加每个委托方法。如果我正在使用特征,当我混合一些特征时,我会自动“污染”Foo界面中的特征方法。有没有什么方法可以实现C++的私有继承?

我想到的唯一解决方案是将特征方法声明为protected并将特征标记为包私有。这种方法在Foo中可见,但在包外,有人无法写val bar:Bar = new Foo。此外,如果我理解正确,只有当包私有特征源代码将在我的项目中时才会验证包私有约束,因为JVM无法表示包私有的概念,编译器只是在字节码中公开它。

1 个答案:

答案 0 :(得分:1)

总之:蛋糕。蛋糕模式。关于它的文章已经写得很多,最边缘,但是一旦这个概念点击了你的脑海,它很容易实现。它是实现SOLID以及可测试性和静态类型依赖注入以及混合和匹配组件化代码的绝佳工具。

它有一个代价,但我曾经觉得价格需要一个特定的理由来使用Cake代码的给定位,我现在看到它反过来了。你应该根据具体情况证明不使用它。

关于蛋糕的开创性论文是Scalable Component Abstractions(这是一个付费专区,但在“网络”的其他地方可以免费获得)。尽管如此,与大多数此类事情一样,这不是最佳起点。只需在网上搜索" Scala Cake Pattern"产生许多命中。阅读一些内容,直到找到一个能够让你明白的东西......