Java 使用mockito在另一个spring服务中模拟服务

Java 使用mockito在另一个spring服务中模拟服务,java,spring,junit4,mockito,spring-test,Java,Spring,Junit4,Mockito,Spring Test,在Spring框架中,我面临着模拟注入到其他服务中的服务的问题。这是我的密码: @Service("productService") public class ProductServiceImpl implements ProductService { @Autowired private ClientService clientService; public void doSomething(Long clientId) { Client clien

在Spring框架中,我面临着模拟注入到其他服务中的服务的问题。这是我的密码:

@Service("productService")
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ClientService clientService;

    public void doSomething(Long clientId) {
        Client client = clientService.getById(clientId);
        // do something
    }
}
我想在测试中模拟
ClientService
,因此我尝试了以下方法:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/spring-config.xml" })
public class ProductServiceTest {

    @Autowired
    private ProductService productService;

    @Mock
    private ClientService clientService;

    @Test
    public void testDoSomething() throws Exception {
        when(clientService.getById(anyLong()))
                .thenReturn(this.generateClient());

        /* when I call this method, I want the clientService
         * inside productService to be the mock that one I mocked
         * in this test, but instead, it is injecting the Spring 
         * proxy version of clientService, not my mock.. :(
         */
        productService.doSomething(new Long(1));
    }

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

    private Client generateClient() {
        Client client = new Client();
        client.setName("Foo");
        return client;
    }
}

productService
中的
clientService
是Spring代理版本,而不是我想要的模拟版本。有可能用Mockito实现我想要的吗?

有更多的方法来实现这一点,最简单的方法是
不要使用字段注入,而使用setter注入
,这意味着您应该:

@Autowired
public void setClientService(ClientService clientService){...}
在服务类中,您可以将模拟注入测试类中的服务:

@Before
public void setUp() throws Exception {
    productService.setClientService(mock);
}

<代码>重要:如果这只是一个单元测试,请考虑不要使用<代码> SpRunJuniT4CaseRun.class < /C> >,但是<代码> MockitoJunitRunner .class < /C> >,这样您也可以为字段使用字段注入。 您需要用

@InjectMocks
注释
ProductService

@Autowired
@InjectMocks
private ProductService productService;
这将把
ClientService
mock注入到您的
ProductService

@Autowired
@InjectMocks
private ProductService productService;
添加以下方法

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}

我建议您使用
@InjectMock

目前

    @Autowired
    private ProductService productService;

    @Mock
    private ClientService clientService;
改为

    @InjectMock
    private ProductService productService;

    @Mock
    private ClientService clientService;
如果MockingService=>仍有NullPointerException,则可以使用Mockito.any()作为参数。
希望它能对你有所帮助。

谢谢Debojit,但我意识到没有办法将spring的注入与mockito的模拟注入结合使用。。。因此,我的解决方案是手动创建ProductService,并像您所说的那样使用
@InjectMocks
注入mock,但不使用
@Autowired
@InjectMocks private ProductService ProductService=new ProductServiceImpl()这很奇怪。我一直在同时使用这两个注释。你测试过了吗。同时使用这两个组件时是否有任何异常。是的,我对它进行了大量测试,即使使用ProductService上的
@InjectMocks
,其中的clientService也是使用spring代理而不是模拟对象加载的。也许你正在使用的spring测试版本与我正在使用的不同,我的版本是3.0.1.RELEASE,你的版本是什么?我正在使用3.1.2.RELEASE和mockito 1.9.5,我改为3.1.2-RELEASE,得到了相同的结果。。。也许您的配置在某些方面与我的不同,好吧,无论如何,谢谢,因为现在我将使用手动实例化方法。谢谢,我尝试了该解决方案,效果很好,但我无法在该服务中更改为setter injection,因此我的解决方案是删除测试中的自动连线注释并手动创建服务,如下所示:
@InjectMocks private-ProductService-ProductService=new-productserviceinpl()
@br4zuca您可以使用
@InjectMocks private-ProductService-ProductService-ProductService
,不要初始化它的手册,让mockito来做。我尝试使用
@InjectMocks
将mockito初始化为
产品服务
,但没有工作,因为
产品服务
是一个接口,它抛出:
org.mockito.exceptions.base.MockitoException:type'ProductService'是一个接口
,因此它无法实例化。我找到了一个解决方案,而不是声明
@InjectMock ProductService ProductService
,我将
ProductService
接口更改为impl like
productserviceinpl
,然后在这种形式下,mockito能够自动初始化我的服务,比如:
@InjectMock-productserviceinpl-productService