@MockBean 和@Autowired 同一个服务在一次测试中 class

@MockBean and @Autowired of the same service in one test class

是否有可能以某种方式在同一服务的同一测试中进行 class @MockBean@Autowired

换句话说,我只想为一项测试提供 @MockBean 服务,而对于相同 class 的其他测试,我需要它作为 @Autowired

这取决于@MockBean@Autowired之间的差异。

@Autowired

仅在 SpringContext 中查找该类型的 bean。这意味着如果需要 'autowire' it

,则需要创建该 bean

@MockBean

完全符合您对名称的期望,它创建了一个 'mock' 服务,并将其作为 bean 注入。

所以这个

class MyTest {
   @MockBean
   MyService myService;
}

相当于这个

@Import(MyTest.Config.class)
class MyTest {

   @Autowired
   MyService myService;

   @TestConfiguration
   static class Config {

      @Bean
      MyService myService() {
         return Mockito.mock(MyService.class);
      }
   }
}

因此,如果您需要在其他测试中使用 MyService 类型的不同 bean,则需要在 @TestConfiguration 注释中创建 bean class

@Import(MyTest.Config.class)
class MyTest {

   @Autowired
   MyService myService;

   @TestConfiguration
   static class Config {

      @Bean
      MyService myService() {
         return new MyServiceImpl();
      }
   }
}

或者,在用 @Configuration

注释的 class 中
@Import(MyConfig.class)
class MyTest {
   @Autowired
   MyService myService;
}

@Configuration
public class MyConfig {
   @Bean
   MyService myService() {
      return new MyServiceImpl();
   }
}

我怀疑这里的罪魁祸首是场注入

Olvier Gierke(现为 Drotbohm)写了一篇 blog post 关于为什么场注入是邪恶的。

如果可以切换到构造函数注入,则可以在测试中模拟服务并将模拟传递给要测试的 class。

我只是想在这里留下这个答案作为对其他可能有机会改用构造函数注入的人的建议。

最好的解决办法是把@MockBean改成@SpyBean。在该方法中,您可以这样做:

kotlin

    @SpyBean
    lateinit var serviceMock: Service

    @Test
    fun smallTest()
        `when`(serviceMock.doSomething())
            .thenReturn(false)

        // your test logic
    }