在Spring Boot测试中,@MockBean
和@SpyBean
都是用来替换Spring应用上下文中的beans以方便测试的注解。它们的主要区别在于它们提供的测试替代的行为不同。
@MockBean
@MockBean
会添加一个Mockito mock到Spring应用上下文中。mock对象会代替原来容器中相同类型和限定符的任何bean。由于mock对象不会继承原bean的任何行为,对于没有明确设置行为的方法调用它们通常会返回各种类型的默认值,如null、false、0、empty集合等,并且会记住那些对它们进行过的交互行为。
使用场景: 当你想要完全控制某个bean的行为,不关心其真实逻辑,或者当依赖很复杂且不想涉及它的内部行为时,使用@MockBean
非常合适。
例如:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceTest {
@MockBean
private ExternalService externalService;
@Autowired
private MyService myService;
@Test
public void testMyService() {
when(externalService.callExternal()).thenReturn("Mock Response");
String result = myService.doSomething();
assertEquals("Expected Result Using Mock", result);
}
}
@SpyBean
与@MockBean
不同,@SpyBean
在现有的bean实例上创建了一个spy。spy对象会默认使用它所包装的实例的所有正常行为,但允许你跟踪和更改某些特定交互的行为。换句话说,通过创建一个spy,你可以让正常逻辑运行,同时监控和更改个别方法的行为。
使用场景: 当你仅想更改或监控bean的部分行为,而保持其他行为保持正常时,使用@SpyBean
很有用。
例如:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceTest {
@SpyBean
private MyHelper myHelper;
@Autowired
private MyService myService;
@Test
public void testMyService() {
doReturn("Mock Response").when(myHelper).helpMe();
String result = myService.doSomething();
assertEquals("Expected Result With Real Behavior And Mocking", result);
}
}
在这个例子中,通过@SpyBean
,我们监控了myHelper
的helpMe
方法,并使其返回一个特定的值,而myHelper的其他方法则会保持原有的正常行为。
总结@MockBean
和@SpyBean
的不同:
@MockBean
创建的是完全由Mockito控制行为的伪造对象(Mock)。@SpyBean
创建的是部分模拟的真实对象(Spy),即允许使用原始对象的所有正常行为,同时能够模拟或监视某些调用。
在决定使用@MockBean
还是@SpyBean
时,考虑你是否需要原始bean的真实行为。如果你需要保持bean的原有行为,同时只改变或监控一些方法,使用@SpyBean
适合;如果你想完全控制bean的行为,不需要任何原来的逻辑,使用@MockBean
比较好。