主要依赖:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>2.5.0</version>
<scope>test</scope>
</dependency>
spring-boot项目中添加如下依赖即可:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
主要代码:
import com.demo.domain.entity.DemoEntity;import com.demo.repository.DemoRepository;import com.demo.service.DemoService;import com.demo.view.OrganizationFullView;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.Mockito;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.boot.test.mock.mockito.MockBean;import org.springframework.test.context.junit4.SpringRunner;import static org.assertj.core.api.Assertions.assertThat;/** * Author: liyang * Date: 05/09/2017 1:45 PM * Version: 1.0 * Desc: 使用 @MockBean 进行 service 测试 */@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)public class ServiceImplTest { @Autowired private DemoService demoService; private final String name = "test"; private final Long id = 1L; /** * 使用MockBean,不直接调用dao层方法,即不产生真实的数据库交互 */ @MockBean private DemoRepository demoRepository; @Before public void setUp() { DemoEntity entity = new DemoEntity(null, name, "", ""); entity.setId(id); Mockito.when(demoRepository.findOne(entity.getId())) .thenReturn(entity); // 对数据库做变更的mock // Mockito.doReturn(demo).when(demoRepository).save(demo); } @Test public void loadDemo() throws Exception { DemoEntity entity = demoService.loadDemo(id); assertThat(entity.getName()).isEqualTo(name); }}
1. 在模拟方法调用时,如果调用处和被调用处传递的对象不能一致(即,需要传递的是同一个对象,但是真正调用时,可能因为反序列化等因素,得到的肯定不是原有对象(即使个属性值一样)),那么我们在模拟调用时,可以使用类似如下代码中updateDemo方法的入参代码块替代传递的对象(4种方式):
BDDMockito.when(demoRepository.updateDemo(org.mockito.Matchers.isA(DemoObject.class))).thenReturn(result);BDDMockito.when(demoRepository.updateDemo(org.mockito.Matchers.any(DemoObject.class))).thenReturn(result);BDDMockito.when(demoRepository.updateDemo(org.mockito.Matchers.any())).thenReturn(result);BDDMockito.when(demoRepository.updateDemo(org.mockito.Matchers.anyObject())).thenReturn(result);
2. 在模拟方法调用时,如果调用处使用matchers的isA、any(Type.class)、any和anyObject方法充当参数时,如果有多个参数,必须所有的参数都通过matchers的方式提供,否则会报异常:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers! m matchers expected, n recorded: ……其中,m表示有m个参数需要通过matchers(参数匹配器)方式提供,n表示只有n个参数通过该方式提供,还有m-n个也必须通过该方式提供。当然被mock方法,参数可以全为非matcher提供或全为matchers方式提供。比如:
错误:when(demo.updateDemo(null,any(Type.class))).thenReturn(result)
正确:when(demo.updateDemo(eq(null),any(Type.class))).thenReturn(result)
正确:when(demo.updateDemo(null,type)).thenReturn(result)
service层被测试方法:
public DemoEntity loadDemo(Long id) { DemoEntity demo = demoRepository.findOne(id); return demo;}