2016-02-25 47 views
1

我正在使用Play Framework 2.3.x,並且我想測試對特定路由(如「/」(其路由器使用多個嵌套的@Inject依賴關係))的調用結束通過調用注入組件的特定方法。在使用FakeRequest時嘲笑內部依賴關係

例如,一個典型的控制器:

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(...); } 
    ... 

我想嘲笑調用()並檢索它的參數來檢查它們是否包含預期的事情。

@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

問題原因,您的DI噴射不知道這是你的模擬

@Mock ExternalService externalService; 

Spring上下文豆集和模擬的Mockito初始設置沒有任何交集東西。

要解決這個問題,您應該將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. 定義從MyControllerTest.MyConfig爲Spring DI額外豆源;
  2. in mockExternalService方法手動創建你的bean-mock;
  3. 定義這個模擬是外部服務的主要實現,並且...
  4. ...讓Spring知道你的bean-mock並在系統中的任何地方自動裝載模擬。

@Autowired 
ExternalService externalService; 

後,您可以在測試中照常模擬工作。例如。定義此行爲

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

感謝您的解釋。它按預期工作。 –