我正在使用Play Framework 2.3.x,我想测试一个特定路由的调用,例如“/”(它的路由器正在使用几个嵌套的@Inject依赖项)通过调用特定方法来结束注射成分。
例如,一个经典的控制器:
public class MyController extends Controller {
@Inject private MyService myService;
public Result index() { myService.foo(); }
...
服务impl注入了我想要模拟的另一个服务:
@Service
public class MyServiceImpl implements MyService {
@Inject private ExternalService externalService;
public void foo() { externalService.call(...); }
...
我想模拟call()并检索它的args以检查它们是否包含预期的东西。
@RunWith(SpringJUnit4ClassRunner.class)
@Profile("test")
@ContextConfiguration(classes = ApiConfiguration.class)
public class MyControllerTest {
@Test public void test() {
Result result = routeAndCall(new FakeRequest("GET", "/"), 10000);
// here, I expect to retrieve and test the args of a mocked externalService.call
}
}
我正在使用FakeRequest调用路由(并且不注入控制器并手动调用该方法),以便考虑某些注释并使用http上下文(在某些区域中使用)。
我正在使用Mockito,我已经尝试了几个combinaison但是无法注入我的模拟(真正的方法总是被调用),例如:
@Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
@Mock ExternalService externalService;
...
when(externalService.call().then(invocation -> {
Object[] args = invocation.getArguments();
有可能吗?你有什么想法吗?
我偶然发现https://github.com/sgri/spring-reinject/似乎适合(没有经过测试),但我不想使用另一个项目,我觉得可以不用。
感谢。
答案 0 :(得分:1)
你的DI注射器对你的模拟
一无所知的问题@Mock ExternalService externalService;
Spring上下文bean集和Mockito mock set最初没有任何交集。
要解决此问题,您应该将mock定义为Spring配置的一部分。例如。像这样
@RunWith(SpringJUnit4ClassRunner.class)
@Profile("test")
@ContextConfiguration(classes = {ApiConfiguration.class, MyControllerTest.MyConfig.class})
public class MyControllerTest {
@Autowired
ExternalService externalService;
@Test public void test() {
...
}
@Configuration
public static class MyConfig {
@Bean
@Primary // it tells Spring DI to select your mock instead of your real ExternalService impl
public ExternalService mockExternalService() {
return Mockito.mock(ExternalService.class);
}
}
}
使用此代码
mockExternalService
方法中手动创建你的bean-mock; 在此之后
@Autowired
ExternalService externalService;
您可以像往常一样在测试中使用模拟。例如。定义此行为
Mockito.doThrow(NullPointerException.class).when(externalService).call(...);