使用FakeRequest时模拟内部依赖

时间:2016-02-25 18:54:10

标签: java playframework dependency-injection mockito

我正在使用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/似乎适合(没有经过测试),但我不想使用另一个项目,我觉得可以不用。

感谢。

1 个答案:

答案 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);
     }     
  }
}

使用此代码

  1. 为Spring DI的MyControllerTest.MyConfig定义其他bean源代码;
  2. mockExternalService方法中手动创建你的bean-mock;
  3. 定义此mock是ExternalService的主要实现,并且......
  4. ...让Spring知道你的bean-mock并在你系统的任何地方自动装配模拟器。
  5. 在此之后

    @Autowired 
    ExternalService externalService;
    

    您可以像往常一样在测试中使用模拟。例如。定义此行为

    Mockito.doThrow(NullPointerException.class).when(externalService).call(...);