Spring配置-注入模拟bean

Spring配置-注入模拟bean,spring,junit,mockito,Spring,Junit,Mockito,我正在使用Spring、Junit和Mockito。我需要使用另一个mockito测试配置(仅在需要时注入模拟bean)覆盖主spring配置中定义的bean。嵌套bean已在应用程序中进行了@Autowired 更新: 根据下面的答案,添加name属性非常重要,这样spring就可以允许主bean(mock)覆盖原始bean。否则会出现以下异常: org.mockito.exceptions.misusing.MissingMethodInvocationException: when()需要

我正在使用Spring、Junit和Mockito。我需要使用另一个mockito测试配置(仅在需要时注入模拟bean)覆盖主spring配置中定义的bean。嵌套bean已在应用程序中进行了
@Autowired

更新:
根据下面的答案,添加
name
属性非常重要,这样spring就可以允许主bean(mock)覆盖原始bean。否则会出现以下异常:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when()需要的参数必须是“模拟的方法调用”。
例如:
when(mock.getArticles())。然后返回(articles)

spring日志中的信息消息显示:
跳过[BeanMethod:name=bar,declaringClass=test.package.MockitoTestConfiguration]的bean定义:bean“bar”的定义已经存在。此顶级bean定义被视为覆盖。

示例:
下面我有一个简单的例子。这里,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);
    }
}

基于
ConfigurationClassBeanDefinitionReader
代码,我猜您正在使用xml配置来定义主bean。如果是这样,在创建mockitobean时只需添加一个名称

@Bean(name="mockbar") 
@Primary 
public Bar bar() {
    logger.debug("injecting mock bar");
    return Mockito.mock(Bar.class);
}
这样,Spring将允许您同时拥有这两个bean,并且当您使用
@Primary
时,它将是您的测试所使用的bean


或者,如果您使用Mockito,您可以这样做,并在测试配置文件中完全取消额外的MockitoTestConfiguration类和命名的主mockbean。就这么简单:

@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);
    }
}

我补充了更多细节。增加一个名字并不能解决我想要达到的目标。这些bean是自动连接的。我看不出自动连接的bean有任何问题。那很好。使用名称是否会出现相同的“错误”?很抱歉,我的配置文件存在其他一些配置问题,导致我以前的测试无法运行。我用
name
属性重新测试了它,结果很好。另外,我不需要
@injectmock
。我会为他人的利益而更新。