简体   繁体   中英

Mocking scala object

I am using mockito and trying to mock a scala object.

object Sample { }
//test
class SomeTest extends Specification with ScalaTest with Mockito {
    "mocking should succeed" in {
        val mockedSample = mock[Sample]
     }
}

This gives me two compilation errors.

error: Not found type Sample
error: could not find implicit value for parameter m:
scala.reflect.ClassManifest[<error>]

If I change Sample from object to class it works. Is is possible to mock scala objects with mockito? If yes how?

As written, your Sample is a pure singleton. Its type is its own and there is only one member of that type, period. Scala object s can extend another class (possibly abstract, if it supplies the necessary definitions to make it a concrete) and traits. Doing that gives it a type identity that includes those ancestors.

I don't know what Mockito is really doing, but to my mind, what you're asking for is strictly at odds with what a Scala object is.

Keep in mind that you can mock the methods of an object if you lift them to functions.

case class Person(name: String)
object Person {
  def listToJson(lp: List[Person]) = "some actual implementation"
}

class ClassUnderTest(listToJson: (List[Person]) => String = Person.listToJson(_)) {
  def testIt(lp: List[Person]) = listToJson(lp)
}

import org.specs._
import org.specs.mock.Mockito
import org.mockito.Matchers._  

class ASpec extends Specification with Mockito {
  "a thing" should {
    "do whatever" in {
      val m = mock[(List[Person]) => String]
      val subject = new ClassUnderTest(m)
      m(Nil) returns "mocked!"
      subject.testIt(Nil) must_== "mocked! (this will fail on purpose)"
    }
  }
}

Here I'm not mocking the object Person, but the method on it (which is probably what the OP was intending).

The test result shows the mocking works:

[info] == ASpec ==
[error] x a thing should
[error]   x do whatever
[error]     'mocked![]' is not equal to 'mocked![ (this will fail on purpose)]' (ASpec.scala:21)
[info] == ASpec ==

Meanwhile, the production-time usage of the ClassUnderTest is simply new ClassUnderTest due to the injected function being a default argument.

Since version 1.16.0 of mockito-scala it is possible to mock Scala object s, you can check the docs here , but this is an example of how it would look like.

object FooObject {
 def simpleMethod: String = "not mocked!"
}

"mock" should {
 "stub an object method" in {
   FooObject.simpleMethod shouldBe "not mocked!"

   withObjectMocked[FooObject.type] {
     FooObject.simpleMethod returns "mocked!"
     //or
     when(FooObject.simpleMethod) thenReturn "mocked!"

     FooObject.simpleMethod shouldBe "mocked!"
   }

   FooObject.simpleMethod shouldBe "not mocked!"
 }
}

我最近发布了ScalaMock ,这是一个用于 Scala 的模拟库,除其他外,它可以模拟单例(和伴随)对象。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM