使用 ScalaTest 测试包含 @Autowired 和私有字段的 java

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

我已经开始使用 ScalaTest 来测试我的 Java 代码并且我喜欢它(我已经阅读了 "Testing in Scala" 这本书)。

最近我一直在尝试测试一些 java Spring 代码,其中包含标记为 private@Autowired 的字段。这些字段没有 setter 方法。

我意识到我可以使用注释 @InjectMocks@Mock 使用 JUnit + Mockito 轻松测试它们,但是,我想使用 ScalaTest 和模拟框架(例如 Mockito或 ScalaMock)。

我的问题:Scalatest + Mockito 能否用于模拟私有字段或这些框架是否要求我的 java 类 定义了 public setter 方法对于我的 private + @Autowired 字段?

根据我的经验,向那些自动装配的 bean 添加设置器要好得多。否则,您要注入所需行为的唯一方法是通过复杂的反射过程,这只会使事情复杂化。

要明确表示不在测试之外使用设置器,您可以做几件事:

  • 将它们标记为包私有

    void setDao(final Dao dao) {
        this.dao = dao;
    }
    
  • 用来自 Guava 的 @VisibleForTesting 注释它们

或者,现在可能是重新审视自动装配方案的好时机;如果你有很多自动连接的 bean,它会变得非常笨重。

您可以在 import org.mockito.MockitoAnnotations.Mock

中使用 @Mock 注释

@Mock private var someDao:SomeDao =_

这有效但不建议使用。它也被弃用了

您可以使用 InjectMocks 来完成。这是一个使用 ScalaTest 和 Mockito 测试包含 @Autowired 成员的 class 的工作示例:

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