我想通过在测试期间提供模拟对象来测试我的 Play 应用程序。在我的脑海中,有几种方法可以解决这个问题。
- 在测试期间提供替代路由文件
- 使用依赖注入,并在运行时检查全局值
我不确定哪个更可行,或者如何去做。任何见解将不胜感激。
我想通过在测试期间提供模拟对象来测试我的 Play 应用程序。在我的脑海中,有几种方法可以解决这个问题。
我不确定哪个更可行,或者如何去做。任何见解将不胜感激。
还有第三种方式;将您的控制器创建为用于测试的类或特征。这是一个简单的例子。
你的特质+实现:
package services
trait MyService {
def getUser(id:String):User
}
class ConcreteService extends MyService {
override def getUser(id:String):User = {
//Do real stuff
}
}
在您的控制器类中:
package controllers
import services._
class Users(service: MyService) extends Controller {
def show(id: String) = Action {
val user = service.getUser(id)
Ok(views.html.user(user))
}
}
object Users extends controllers.Users(new ConcreteService()) {}
现在你可以运行一些单元测试..
package test
import controllers.Users
import play.api.test._
import play.api.test.Helpers._
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification
class UsersSpec extends Specification with Mockito {
val service = mock[MyService]
"Users controller" should {
"list users" in {
//Insert mocking stuff here
val users = new Users(service)
val result = users.show("somerandomid")(FakeRequest())
status(result) must equalTo(OK)
}
}
}
我的解决方案类似于 Blake 的解决方案,只是我在没有控制器作为类的情况下做到了。你可以在这里查看源代码。
作为参考,我添加了一个使用 Play 的插件框架在测试期间注入模拟对象的示例。
使用此方法可以在测试时提供模拟插件:
class Test extends Specification {
"application" should {
"load mock dependency" in {
running(TestServer(9000, FakeApplication(
// The plugin at this class replaces the default
additionalPlugins = Seq("test.MockInjector")
)), HTMLUNIT) { browser =>
browser.goTo("http://localhost:9000")
// Test mock controller
}
}
}
}
可MockInjector
用于提供控制器对象或任何其他可注入组件。
注意:我写了博客条目,任何人都可以自由地将博客中的任何和所有内容迁移到这里。