我有一个接口,它注册为 ServiceLocatorFactoryBean 的一部分。该接口的主要目的是充当工厂。
我已经在各种类中“自动装配”了这个接口,我现在想用 Mockito 进行测试。
问题是 Mockito 不支持接口。如何在我正在测试的类中注入这个接口的模拟。
我看到的唯一替代方法是使用 SpringJunitRunner 运行测试并提供具有 bean 配置的 Application Context。但这太冗长了。
我有一个接口,它注册为 ServiceLocatorFactoryBean 的一部分。该接口的主要目的是充当工厂。
我已经在各种类中“自动装配”了这个接口,我现在想用 Mockito 进行测试。
问题是 Mockito 不支持接口。如何在我正在测试的类中注入这个接口的模拟。
我看到的唯一替代方法是使用 SpringJunitRunner 运行测试并提供具有 bean 配置的 Application Context。但这太冗长了。
我认为您想监视 Spring 为您的接口生成的实现?!到目前为止,这几乎是不可能实现的……但是,下面至少有以下替代方案。
假设我们有以下设置:
public interface MyService {
String doIt();
}
@Component
public static class ServiceConsumer {
@Autowired
private MyService service;
public String execute() {
return service.doIt();
}
}
0)后来编辑:在漫游时,我发现使用Springockito-annotations可以监视甚至用模拟替换自动装配的字段,而且也相当容易。
@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan
@ContextConfiguration(loader = SpringockitoAnnotatedContextLoader.class, classes = {SpringockitoConsumerTest.class})
public class SpringockitoConsumerTest {
@WrapWithSpy(beanName = "myService")
@Autowired
private MyService mockService;
@Autowired
private ServiceConsumer consumer;
@Test
public void shouldConsumeService() {
assertEquals("allDone", consumer.execute());
verify(mockService).doIt();
}
}
如果Springockito-annotations
没有问题,请参阅下面的 2 个原始建议
1)你可以创建你的接口模拟并在你的bean中自动注入Mockito。这是最简单的解决方案(我在撰写本文时能想到),但它不能确保@Autowired
消费者不会忘记注释(也许可以添加专门的测试?!):
public class AutoInjectMocksConsumerTest {
@Mock
private MyService serviceMock;
@InjectMocks
private ServiceConsumer consumer = new ServiceConsumer();
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
when(serviceMock.doIt()).thenReturn("allDone");
}
@Test
public void shouldConsumeService() {
assertEquals("allDone", consumer.execute());
verify(serviceMock).doIt();
}
}
2) 或者,正如您所说的那样,您可以SpringJunitRunner
以最少的努力来运行它来定义和实例化必要的 Spring 上下文,同时还提供您自己的服务模拟。尽管人们可能会抱怨这个解决方案不是那么干净,但我发现它足够优雅,并且它还验证了@Autowired
注释在消费者实现中没有被遗忘。
@RunWith(SpringJUnit4ClassRunner.class)
@Configuration
@ComponentScan
@ContextConfiguration(classes = {SpringAutowiringConsumerTest.class})
public class SpringAutowiringConsumerTest {
@Autowired
private MyService mockService;
@Autowired
private ServiceConsumer consumer;
@Test
public void shouldConsumeService() {
assertEquals("allDone", consumer.execute());
verify(mockService).doIt();
}
@Bean
public MyService mockService() {
MyService serviceMock = mock(MyService.class);
when(serviceMock.doIt()).thenReturn("allDone");
return serviceMock;
}
}