我正在使用Spring,Junit和Mockito。我需要使用另一个mockito测试配置覆盖主弹簧配置中定义的bean(仅在需要时注入模拟bean)。嵌套bean在应用程序中已@Autowired
。
更新
根据下面alfcope的答案,重要的是添加name
属性,以便spring可以允许主bean(模拟)覆盖原始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.
示例:
我在下面有一个简化的例子。在这里,Bar是嵌套在Foo中的,我需要模拟Bar进行测试:
@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而不是真正的bar。我怎样才能在下面的测试课中实现这一目标?
@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);
}
}
答案 0 :(得分:2)
根据ConfigurationClassBeanDefinitionReader
代码,我猜您使用xml配置来定义主bean。如果是这样,只需在创建mockito bean时添加一个名称。
@Bean(name="mockbar")
@Primary
public Bar bar() {
logger.debug("injecting mock bar");
return Mockito.mock(Bar.class);
}
这样Spring就可以让你拥有这两个bean,当你使用@Primary
时,它将是你的测试使用的那个。
答案 1 :(得分:0)
或者,如果您使用Mockito,您可以执行此操作并完全取消额外的MockitoTestConfiguration类并在测试配置文件中命名主模拟bean。只需这样做:
@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);
}
}