Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito for Objects in Scala

I'm using Scala 2.10, specs2 and Mockito. I want to mock scala.io.Source.fromURL(). The issue seems to be fromURL() is a function in io.Source's object.

val m = mock[io.Source]
m.fromURL returns io.Source.fromString("Some random string.")

It's a pretty straightforward mock in an Unit test. Why isn't it working?

Thanks!

like image 967
Marius Stroe Avatar asked May 08 '13 14:05

Marius Stroe


People also ask

Can I mock object in Scala?

ScalaMock is a native, open-source Scala mocking framework written by Paul Butcher that allows you to mock objects and functions. ScalaMock supports three different mocking styles: Function mocks. Proxy (dynamic) mocks.

Can we use Mockito in Scala?

Mockito is one of the most popular mocking frameworks in the JVM. In this tutorial, let's look at different ways in which we can use Mockito with ScalaTest to test our Scala code.

What is MockitoSugar?

MockitoSugar trait provides some basic syntax sugar for Mockito. Using the Mockito API directly, you create a mock with: val mockCollaborator = mock(classOf[Collaborator]) Using this trait, you can shorten that to: val mockCollaborator = mock[Collaborator]

What is difference between object and class in Scala?

Difference Between Scala Classes and Objects Definition: A class is defined with the class keyword while an object is defined using the object keyword. Also, whereas a class can take parameters, an object can't take any parameter. Instantiation: To instantiate a regular class, we use the new keyword.


2 Answers

Good news! With the latest 1.16 release of mockito-scala, you can now mock scala objects.

To enable withObjectMocked feature, it is mandatory to create the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line:

mock-maker-inline 

Example:

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

See: https://github.com/mockito/mockito-scala#mocking-scala-object

like image 118
krismath Avatar answered Nov 14 '22 10:11

krismath


Instead of mocking it, you could try spying it as follows:

val m = spy(io.Source)

Or you could mock it as follows:

val m = mock[io.Source.type]

But then how are you using Source in the class you are testing? If you had an example class like so:

class MyClass{

  def foo = {
    io.Source.doSomething //I know doSomething is not on Source, call not important
  }
}

Then in order to take advantage of mocking/spying, you'd have to structure your class like so:

class MyClass{
  val source = io.Source
  def foo = {
    source.doSomething
  }
}

And then your test would have to look something like this:

val mockSource = mock[io.Source.type]
val toTest = new MyClass{
  override val source = mockSource
}

In the Java world, static methods are the bane of mocking. In the Scala world, calls to objects can also be troublesome to deal with for unit tests. But if you follow the code above, you should be able to properly mock out an object based dependency in your class.

like image 31
cmbaxter Avatar answered Nov 14 '22 11:11

cmbaxter