2017-06-22 269 views
0

我正在使用Spring,Junit和Mockito。我需要使用另一個mockito測試配置(僅在需要時注入模擬Bean)來覆蓋主彈簧配置中定義的bean。在應用程序中嵌套豆已@Autowired彈簧配置 - 注入模擬豆

更新:
基於以下alfcope的答案,重要的是要添加name屬性,以便彈簧能夠使主Bean(模擬)取代原來的一個。否則,你得到這個異常: org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'. For example: when(mock.getArticles()).thenReturn(articles);

春天日誌的信息消息顯示:
Skipping bean definition for [BeanMethod:name=bar,declaringClass=test.package.MockitoTestConfiguration]: a definition for bean 'bar' already exists. This top-level bean definition is considered as an override.

例子:
下面我有一個可行的簡化的例子。在這裏,酒吧是嵌套在富了,我需要模擬酒吧來進行測試:

@Component 
public class Foo 
{ 
    @Autowired 
    private Bar bar; 

    public String getResponseFromBar(String request) 
    { 
     String response = bar.someMethod(String request); 
     //do something else with this reponse 
     return response; 
    } 

} 

@Component 
public class Bar { 
    public String someMethod(String request) { 
     String response = null; 
     //do something 
     return response; 
    } 
} 

現在進行測試,讓我們說我想注入mockbar,而不是真正的吧。我如何在下面的測試課中實現這一點?

@Profile("test") 
@Configuration 
public class MockitoTestConfiguration { 

    //adding the name attribute is important. 
    @Bean(name="mockBar") 
    @Primary 
    public Bar bar() { 
     logger.debug("injecting mock bar"); 
     return Mockito.mock(Bar.class); 
    } 
} 

實際測試情況:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath*:test-context.xml") 

public class FooTest { 

    @Autowired 
    Foo foo; 
    @Autowired 
    Bar mockBar; //need this to set up the mock response in the test case. 

    @Test 
    public void testAMethodInFoo_WithBarInjectedByMockito() { 

     //set up the mockBar response 
     Mockito.when(mockBar.someMethod("1")).thenReturn("1-response"); 

     String response = foo.getResponseFromBar(); 
     assertEquals("1-response", response); 
    } 
} 

回答

1

基礎上ConfigurationClassBeanDefinitionReader代碼我猜你正在使用XML配置來定義你的主要豆。如果是這樣,只需在創建mockito bean時添加一個名稱即可。

@Bean(name="mockbar") 
@Primary 
public Bar bar() { 
    logger.debug("injecting mock bar"); 
    return Mockito.mock(Bar.class); 
} 

這樣,春天可以讓你同時擁有豆類,和你正在使用@Primary這將是你的測試中使用的一個。

Spring overriding primary bean with non-primary bean

ConfigurationClassBeanDefinitionReader Code

+0

我增加了更多的細節。添加一個名字並不能解決我想要達到的目標。這些bean是自動裝配的。 – code4kix

+0

我看不到任何自動裝配bean的問題。沒事兒。你是否使用名字獲得相同的「錯誤」? – alfcope

+0

對不起,我有一些配置文件,導致我以前的測試不工作的配置問題。我用'name'屬性重新測試,它工作得很好。另外,我不需要'@InjectMocks'。我會爲了其他人的利益而更新。 – code4kix

0

另外,如果你使用的Mockito,你可以做到這一點,完全廢除測試配置文件中的額外MockitoTestConfiguration類,並命名爲主要模擬豆類。只是簡單地這樣做:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath*:test-context.xml") 

public class FooTest { 

    @Autowired 
    @InjectMocks 
    Foo foo; 
    @Mock 
    Bar mockBar; //need this to set up the mock response in the test case. 

    @Before 
    public void setUp() throws Exception { 
     MockitoAnnotations.initMocks(this); 
    } 

    @Test 
    public void testAMethodInFoo_WithBarInjectedByMockito() { 

     //set up the mockBar response 
     Mockito.when(mockBar.someMethod("1")).thenReturn("1-response"); 

     String response = foo.getResponseFromBar(); 
     assertEquals("1-response", response); 
    } 
}