Using spoof object as implicit in scala using scalamoka

I use trait definition with various concrete derivatives and implicit to inject dependencies into objects as well as wear out parts of the system when unit testing. The problem is that when the fictitious version of the type is used as an implicit declaration, it doesn't match scala in the consuming object.

Here's a simplified version of my setup. Is there a way to get Test1 to work with a mock. Test2 works great, but is difficult to maintain and requires too much customization.

Model:

case class User (first: String, last: String, enabled: Boolean)

      

Component definition:

trait DataProviderComponent {
  def find[T](id: Int): Try[T]
  def update[T](data: T): Try[T]
}

      

One of the concrete implementations of the components:

class DbProvider extends DataProviderComponent {
  override def find[T](id: Int): Try[T] = { ... }
  override def update[T](data: T): Try[T] = { ... }
}

      

Implicit use of an impl component somewhere in the system:

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
  }
}

      

Unit Test1 trying to mock the provider to isolate the test repository. This does not work, the repository class is not the same as the implicit one, even if it is based on the 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)
  }
}

      

This version works, but is difficult to maintain and requires more code:

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)
  }
}

      

Is there a way to use the fictional type as implicit input - or is there another scala-like pattern I should use to solve this problem?

+1


source to share


1 answer


This code compiles and runs successfully for me

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)
  }
}

      

+2


source







All Articles