Mockito:模拟间接注入的单例

时间:2018-08-21 03:12:08

标签: kotlin mockito guice apache-storm

我有一个风暴螺栓类,其中有很多通过guice注入字段的依赖项,其中一个MyMapper是单例:

class MyBolt(val injector: Injector): BaseRichBolt {
  ...
  @Inject
  @Transient
  private lateinit var myMapper: MyMapper

  override fun prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
    super.prepare()
    // actually inject the fields
    this.injector.injectMembers(this)
  }

  override fun execute(input: Tuple) {
    // use myMapper here to query database
    val value: String = myMapper.read(someKey)
    ...
  }
}

@Singleton
class MyMapper @Inject constructor(private val myDAO: MyDAO) {
  ...
  fun read(key: String): String {
    // use myDAO to read from database
    return ...
  }
}

我正在为螺栓编写测试,并且想模拟myMapper,以便实际上不需要去数据库读取某些value。在我的测试课中,我尝试如下模拟它:

class MyTest {
  private lateinit var injector: Injector
  private lateinit var myBolt: MyBolt

  private fun createInjector() : Injector {
    // create the injector with my guice modules
    ...
  }

  @Before
  fun setUp() {
    injector = createInjector()
    myBolt = Mockito.spy(MyBolt(injector))
  }

  @InjectMocks private val myMapper: MyMapper = mock(MyMapper::class.java)
  ...
  @Test
  fun test1() {
    ...
    Mockito.`when`(myMapper.read(any()).thenReturn("something")
    ...
    // execute on a test tuple and verify some method got called
    myBolt.execute(someTuple)
    verify(myBolt).someMethod(any())
  }
}

我希望以上内容将呼叫重定向到myMapper.read()以返回something。但是它仍然尝试从数据库中读取。有什么想法可以做到吗?

1 个答案:

答案 0 :(得分:0)

通过使用MockitoJUnitRunner.class作为运行程序,或者通过调用Mockito.initMocks(this),都缺少了模拟的实际初始化。

类似的东西:

@RunWith(MockitoJUnitRunner.class)
class MyTest {
    // everything as it is right now
}

或者:

class MyTest {

    @Before
    fun setUp() {
        injector = createInjector()
        myBolt = Mockito.spy(MyBolt(injector))
        Mockito.initMocks(this)
    }

    // everything else
}