0

I have begun to use ScalaTest to test my Java code and I like it (I've read the "Testing in Scala" book).

Recently I've been trying to test some java Spring code that contain fields which are marked private and @Autowired. There are no setter methods for these fields.

I realise that I could easily test them using JUnit + Mockito using the annotations @InjectMocks and @Mock, however, I would like to test them using ScalaTest and a mocking framework (such as Mockito or ScalaMock).

My question: Can Scalatest + Mockito be used to mock out private fields or do these frameworks require that my java classes have a public setter method defined for my private + @Autowired fields?

Rob O'Doherty
  • 549
  • 3
  • 14

3 Answers3

3

You can do it with InjectMocks. Here's a working example using ScalaTest and Mockito to test a class containing @Autowired members:

import org.mockito.{MockitoAnnotations, InjectMocks, Mock}
import org.scalatest.{FunSpec, BeforeAndAfter}
import org.scalatest.Matchers._
import org.mockito.Mockito._
import org.springframework.beans.factory.annotation.Autowired

class InjectMocksSpec extends FunSpec with BeforeAndAfter {

  @Mock
  var paramMock: MockedClass = null

  @InjectMocks
  var testClass = new TestClass()

  describe("InjectMocks") {
    it("should inject mock for Autowired field") {
      MockitoAnnotations.initMocks(this)

      when(paramMock.get).thenReturn("bar")

      testClass.test should be("bar")

      verify(paramMock, times(1)).get
    }
  }

}

class MockedClass {
  def get: String = {
    "foo"
  }
}

class TestClass {
  @Autowired
  var param: MockedClass = null

  def test: String = {
    param.get
  }
}
drsquidop
  • 428
  • 4
  • 12
0

In my experience, it's been far better to add setters to those autowired beans. Otherwise, the only way you're going to inject the behavior you want is through a convoluted reflection process, which only serves to complicate matters.

To make it explicit that the setters aren't to be used outside of test, you can do a couple of things:

  • Mark them as package-private

    void setDao(final Dao dao) {
        this.dao = dao;
    }
    
  • Annotate them with @VisibleForTesting from Guava

Alternatively, it may be a good time to revisit the autowiring scheme; it can become very unwieldy if you have a lot of beans that you're automatically wiring in.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • Hi Makoto ... thanks for the quick reply. Both bulleted suggestions are helpful and I will consider using them. However, I'm specifically asking if any of the Mocking frameworks for Scala (e.g. ScalaMock or Mockito with MockitoSugar) will support testing of java code that contains private fields that are not accessible via public accessor methods. Thanks again! – Rob O'Doherty May 15 '15 at 08:04
0

You can use @Mock annotation in import org.mockito.MockitoAnnotations.Mock

@Mock private var someDao:SomeDao =_

this works but is not advisable to use. It is also being deprecated

bugs
  • 1
  • 2