首页 > 解决方案 > Mockito:模拟间接注入的单例

问题描述

我有一个风暴螺栓类,它有很多带有 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()到 return something。但它仍然尝试从数据库中读取。任何想法我怎么能做到这一点?

标签: kotlinmockitoguiceapache-storm

解决方案


您错过了模拟的实际初始化,或者通过使用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
}

推荐阅读