在 Scala 中为测试创建内存存储库的惯用功能方法
Idiomatic functional way to make in memory repository for tests in Scala
我有 2 个问题。
- 我正在使用类型化的 Akka 制作后端并想进行测试。简单的方法,没有依赖注入,自动连接等。所以我有一个特点
trait Repository {
def create(h: Model): Future[Int]
def get(id: Long): Future[Model]
}
所以 2 类 正在扩展特征 - DatabaseRepository
和 InMemoryRepository
InMemoryRepository 应该用于测试。最简单的解决方案是创建 mutable.Map
成员用于存储实体并在每次创建操作时更新它。然而,这正在改变一个状态。我知道这些是测试,但即使在测试中也可能需要同时创建实体。
另一种可能更实用的方法是创建一个创建方法 returns 一个 Tuple (InMemoryRepository, Int) 以便在组合 Futures 或任何效果时传递它。
也许一个解决方案是创建一个简单的 State monad,它将存储一个 Map
,实现 flatMap
方法,该方法可以在 for comprehension 中使用,并在需要时用于所有其他地方,并且隐藏变异状态。
你有更好的方法吗?
- 传递配置值的最佳方法是什么?我创建了一个包对象并在那里有一个变量,如
dbHost
、thirdPartyUrl
(从配置加载)。然后我在需要的地方包含这个包对象。
提前致谢
如果InMemoryRepository
仅用于测试,则完全不需要实现。只需使用模拟。
例如:
val repo = mock[Repository]
val models = Seq(mock[Model], mock[Model], mock[Model])
models.zipWithIndex.foreach { case (m,i) =>
when(repo.create(m)).thenReturn(Future.successful(i+1))
when(repo.get(i+1)).thenReturn(Future.successful(m))
}
或者更简单,具体取决于您实际测试的是什么:
when(repo.create(any)).return(Future.successful(100500))
when(repo.get(any)).return(Future(mock[Model]))
至于传递配置值,经常使用 (implicit config: Config)
之类的东西。
没有单一的、有据可查的方法,但这是我的方法。它有点长,所以我把它放在要点上。
抽象出容器类型,因为在我的项目中我同时使用了 Future 和 IO:
https://gist.github.com/V-Lamp/c8862030a2f9bba4951db985b61719b8
我有 2 个问题。
- 我正在使用类型化的 Akka 制作后端并想进行测试。简单的方法,没有依赖注入,自动连接等。所以我有一个特点
trait Repository {
def create(h: Model): Future[Int]
def get(id: Long): Future[Model]
}
所以 2 类 正在扩展特征 - DatabaseRepository
和 InMemoryRepository
InMemoryRepository 应该用于测试。最简单的解决方案是创建 mutable.Map
成员用于存储实体并在每次创建操作时更新它。然而,这正在改变一个状态。我知道这些是测试,但即使在测试中也可能需要同时创建实体。
另一种可能更实用的方法是创建一个创建方法 returns 一个 Tuple (InMemoryRepository, Int) 以便在组合 Futures 或任何效果时传递它。
也许一个解决方案是创建一个简单的 State monad,它将存储一个 Map
,实现 flatMap
方法,该方法可以在 for comprehension 中使用,并在需要时用于所有其他地方,并且隐藏变异状态。
你有更好的方法吗?
- 传递配置值的最佳方法是什么?我创建了一个包对象并在那里有一个变量,如
dbHost
、thirdPartyUrl
(从配置加载)。然后我在需要的地方包含这个包对象。
提前致谢
如果InMemoryRepository
仅用于测试,则完全不需要实现。只需使用模拟。
例如:
val repo = mock[Repository]
val models = Seq(mock[Model], mock[Model], mock[Model])
models.zipWithIndex.foreach { case (m,i) =>
when(repo.create(m)).thenReturn(Future.successful(i+1))
when(repo.get(i+1)).thenReturn(Future.successful(m))
}
或者更简单,具体取决于您实际测试的是什么:
when(repo.create(any)).return(Future.successful(100500))
when(repo.get(any)).return(Future(mock[Model]))
至于传递配置值,经常使用 (implicit config: Config)
之类的东西。
没有单一的、有据可查的方法,但这是我的方法。它有点长,所以我把它放在要点上。 抽象出容器类型,因为在我的项目中我同时使用了 Future 和 IO: https://gist.github.com/V-Lamp/c8862030a2f9bba4951db985b61719b8