在阶使用嘲笑对象作为隐含使用scalamock(Using a mocked object as a

2019-10-21 07:45发布

我使用与各种混凝土衍生物和隐性性状定义注入的依赖关系为对象,并且还以模拟出系统时的单元测试的部分。 的问题是,当一个类型的嘲笑版本被用作隐式声明,它不是由在消费对象阶匹配。

这是我设置的简化版本。 有没有一种方法使用一个模拟,使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)
  }
}

是否有使用嘲笑类型作为注入含蓄的方式 - 或有另一种斯卡拉-thonic我应该用它来解决这个问题的模式?

Answer 1:

此代码成功编译并运行我

斯卡拉: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)
  }
}


文章来源: Using a mocked object as an implicit in scala using scalamock