Rob O'Doherty
Rob O'Doherty

Reputation: 569

Using ScalaTest to test java that contain @Autowired and private fields

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?

Upvotes: 0

Views: 1373

Answers (3)

drsquidop
drsquidop

Reputation: 438

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

Upvotes: 3

bugs
bugs

Reputation: 1

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

Upvotes: 0

Makoto
Makoto

Reputation: 106490

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.

Upvotes: 0

Related Questions