提问者:小点点

Scala:模拟伴侣对象


我看到了关于如何模拟伴随对象的多个问题,经常提到的答案是使用scalamock,但根据版本3的文档,模拟伴随对象仍然标记为将来。

那么,如何模拟同伴对象呢?如果没有,还有比我已经拥有的启用测试更好的方法吗?

使用play框架的代码:

模型

case class Article(id: String, preview: String)

object Article {
   def get(id: String) = {
     ......
   }
}

文章资源

class ArticleResource extends Controller {
   def getArticle(id: String) = authenticate {
      ......
      Article.get(id)
      ......
   }
}

如何模仿< code>Article.get(id)?

在我让它工作之前,我的代码结构不同:

工作测试方法

模型

case class Article(id: String, preview: String)

服务

class ArticleService {
   def get(id: String) = {
     ......
   }
}

object ArticleService {
   def apply = new ArticleService
}

文章资源

class ArticleResource(articleService: ArticleService) {
   def getArticle(id: String) = authenticate {
      ......
      articleService.get(id)
      ......
   }
}

object ArticleResource extends controllers.ArticleResource(ArticleService())

在测试中,我将mock[ArticleService]注入到资源中进行测试。

我一直听说前一种方法(模型)是“正确”的方法,我一直不明白为什么,所以我尝试了它并在测试中遇到了问题,但我仍然不明白为什么它是更好的方法。(考虑到测试的困难,我现在实际上对后一种方法感觉更强烈)

所以我有两个问题:

  1. 有没有办法模拟伴侣对象?
  2. 是否有“正确”的方法来构建代码,如果有,为什么?

共1个答案

匿名用户

1) 我认为这是不可能的,我也不认为这是个好主意。我认为将需要模仿的行为放在伴随对象中是不可取的。

2) 我也认为你的第一种方法更好。如果您希望将当前代码保持在最小的更改范围内,那么:

case class Article(id: String, preview: String)

object Article {
   def get(id: String) = {
     ......
   }
}

class ArticleResource(articleFinder: (String) => Article = Article.get) {
   def getArticle(id: String) = authenticate {
      ......
      articleFinder(id)
      ......
   }
}

在测试ArticleResource时,你可以创建一个函数String =

编辑:您甚至可以使用伴随对象的方法作为默认值,以便更容易在生产代码中实例化。