模拟服务与另一个弹簧服务与mockito

br4*_*uca 10 java spring spring-test junit4 mockito

我面临着在Spring框架内模拟注入其他服务的服务的问题.这是我的代码:

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

    @Autowired
    private ClientService clientService;

    public void doSomething(Long clientId) {
        Client client = clientService.getById(clientId);
        // do something
    }
}
Run Code Online (Sandbox Code Playgroud)

我想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;
    }
}
Run Code Online (Sandbox Code Playgroud)

clientService内部productService是Spring代理版本,而不是我想要的模拟.我可以用Mockito做我想做的事吗?

Deb*_*kia 5

您需要标注ProductService@InjectMocks

@Autowired
@InjectMocks
private ProductService productService;
Run Code Online (Sandbox Code Playgroud)

这会将ClientService模拟物注入您的ProductService


Jai*_*o99 1

有更多方法可以实现此目的,最简单的方法是,这don't use field injection, but setter injection意味着您应该:

@Autowired
public void setClientService(ClientService clientService){...}
Run Code Online (Sandbox Code Playgroud)

在您的服务类中,然后您可以将模拟注入到测试类中的服务中:

@Before
public void setUp() throws Exception {
    productService.setClientService(mock);
}
Run Code Online (Sandbox Code Playgroud)

important:如果这只是一个单元测试,请考虑不要使用SpringJUnit4ClassRunner.class, but MockitoJunitRunner.class,这样您也可以对您的字段使用字段注入。

  • 我找到了一个解决方案,而不是声明`@InjectMock ProductService ProductService`,我将`ProductService`接口更改为像`ProductServiceImpl`一样的impl,然后以这种形式mockito能够自动初始化我的服务,例如:`@InjectMock ProductServiceImpl 产品服务` (2认同)