我正在使用具有各种具体衍生物的特征定义,并隐含地将依赖性注入对象,并在单元测试时模拟系统的各个部分。问题是当一个类型的模拟版本被用作隐式声明时,它与消费对象中的scala不匹配。
以下是我的设置的简化版本。有没有办法让 Test1 使用模拟工作。 Test2 工作正常,但很难维护,需要设置太多。
模特:
case class User (first: String, last: String, enabled: Boolean)
组件定义:
trait DataProviderComponent {
def find[T](id: Int): Try[T]
def update[T](data: T): Try[T]
}
具体组件实现之一:
class DbProvider extends DataProviderComponent {
override def find[T](id: Int): Try[T] = { ... }
override def update[T](data: T): Try[T] = { ... }
}
在系统的某处隐式使用组件impl:
implicit val provider = new DbProvider()
class UserRepsitory(implicit provider: DataProviderComponent) {
def userEnabled(id: Int): Boolean = {
val user = provider.find[User](id)
user.isSuccess && user.get.enabled
}
}
单元Test1,试图模拟提供程序以隔离存储库测试。这不起作用,尽管存储库类基于DataProviderComponent,但它与隐式类不匹配:
class UserRepository$Test1 extends FunSuite with Matchers with MockFactory {
test("invalid data request should return false") {
implicit val mockProvider = mock[DataProviderComponent]
(mockProvider.find[User] _).expects(13).returns(Failure[User](new Exception("Failed!")))
val repo = new UserRepsitory()
repo.userEnabled(13) should be (false)
}
}
此版本确实有效,但很难维护,需要更多代码:
class UserRepository$Test2 extends FunSuite with Matchers with MockFactory {
test("invalid data request should return false") {
class FakeProvider extends DataProviderComponent {
override def find[T](id: Int): Try[T] = ???
override def update[T](data: T): Try[T] = Failure[T](new Exception("Failed!"))
}
implicit val provider = new FakeProvider()
val repo = new UserRepsitory()
repo.userEnabled(13) should be (false)
}
}
有没有办法使用模拟类型作为注入隐式 - 或者是否有另一个scala-thonic模式我应该用来解决这个问题?
答案 0 :(得分:2)
此代码成功编译并为我运行
scala:2.10.4
scalaTest:2.1.0-RC2
scalaMock:3.1.RC1
import org.scalamock.scalatest.MockFactory
import org.scalatest.{FunSuite, Matchers}
import scala.util.{Failure, Try}
case class User(first: String, last: String, enabled: Boolean)
trait DataProviderComponent {
def find[T](id: Int): Try[T]
def update[T](data: T): Try[T]
}
class DbProvider extends DataProviderComponent {
override def find[T](id: Int): Try[T] = {
???
}
override def update[T](data: T): Try[T] = {
???
}
}
class UserRepository(implicit provider: DataProviderComponent) {
def userEnabled(id: Int): Boolean = {
val user = provider.find[User](id)
user.isSuccess && user.get.enabled
}
}
class UserRepositoryTest extends FunSuite with Matchers with MockFactory {
test("invalid data request should return false") {
implicit val mockProvider: DataProviderComponent = mock[DataProviderComponent]
(mockProvider.find[User] _).expects(13).returns(Failure[User](new Exception("Failed!")))
val repo = new UserRepository()
repo.userEnabled(13) should be(false)
}
}