在 Scala 中为测试创建内存存储库的惯用功能方法

Idiomatic functional way to make in memory repository for tests in Scala

我有 2 个问题。

  1. 我正在使用类型化的 Akka 制作后端并想进行测试。简单的方法,没有依赖注入,自动连接等。所以我有一个特点
trait Repository {
  def create(h: Model): Future[Int]

  def get(id: Long): Future[Model]
}

所以 2 类 正在扩展特征 - DatabaseRepositoryInMemoryRepository

InMemoryRepository 应该用于测试。最简单的解决方案是创建 mutable.Map 成员用于存储实体并在每次创建操作时更新它。然而,这正在改变一个状态。我知道这些是测试,但即使在测试中也可能需要同时创建实体。

另一种可能更实用的方法是创建一个创建方法 returns 一个 Tuple (InMemoryRepository, Int) 以便在组合 Futures 或任何效果时传递它。

也许一个解决方案是创建一个简单的 State monad,它将存储一个 Map,实现 flatMap 方法,该方法可以在 for comprehension 中使用,并在需要时用于所有其他地方,并且隐藏变异状态。

你有更好的方法吗?

  1. 传递配置值的最佳方法是什么?我创建了一个包对象并在那里有一个变量,如 dbHostthirdPartyUrl(从配置加载)。然后我在需要的地方包含这个包对象。

提前致谢

如果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