scala中的单例模式,可以轻松使用模拟

时间:2016-01-12 20:01:43

标签: scala unit-testing singleton

我正在处理一个用例,我的应用程序需要一个特性对象Table。我有一个将在开发环境中使用的实现TableImpl()。但是,我希望能够在测试环境中将TableImpl()MockTableImpl()切换。

最常用的scala方法是什么?

我可以使用工厂来提供TableImpl()的单身人士,但工厂如何决定退回TableImpl()MockTableImpl()

2 个答案:

答案 0 :(得分:1)

我建议反对询问组件的依赖关系。相反,让组件的创建者给它它的依赖关系(依赖注入或控制反转)。这种方法可以更好地适应惯用语。

只是将依赖项作为构造函数参数传递。这样,就无法构建没有有效依赖关系的类:

class MyApp (table: Table) {
   ...
}

class TableImpl() extends Table // singleton

// in production
new MyApp (table = new TableImpl()) // or you can use factory or whatever

// in test (assuming scalatest and scalamock)
new MyApp (table = mock[Table])

答案 1 :(得分:1)

trait Table {
  def size: Int
}

object TableImpl extends Table { //SINGLETON
  def size = Math.abs(-5)*11 //real logic
}

某些应用程序类(它可能扩展App特征)。

class AppContext(table: Table) {
  def run = ()
}

使用单例引用实例化应用程序。

new AppContext(TableImpl).run

或者为测试原因构建应用程序上下文。

val mock = mock[Table]
//set mock stuff
new AppContext(mock).run 

建议您使用MacwireGuice或Cake模式等DI object。我的建议是始终将依赖关系显式化 - 不要直接在类体中使用单个foo.A名称,而是将其注入。