JavaMockito的使用

JavaMockito的使用

  • 我们在写单元测试的时候,有时候不需要去检验某些组件是否正确,我们会默认这些组件正确的情况下测试其他组件,这时候我们可以使用Mocks框架代替其他组件,继续进行单元测试。
  • 模拟场景是Mock Spring-data-mongodb的MongoRepository,测试Service
  • Mockito官网也有非常完善的文档:
    http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html

在maven工程中添加Mockito依赖

<dependency>
    <groupId>org.mockitogroupId>
    <artifactId>mockito-allartifactId>
    <version>1.10.19version>
    <scope>testscope>
dependency>

测试的Model

@Document(collection = "user")
public class MongoUser {
    @Id
    private String id;

    @Indexed
    @Field(value = "name")
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Mock的Repository

public interface MongoUserDao extends MongoRepository<MongoUser, String> {
    List findByName(String name);
}

测试的Service层

@Service
public class UserService {
    @Autowired
    private MongoUserDao mongoUserDao;

    public Observable> findMongoUserByName(String name) {
        Observable> ob = Observable.create(observer -> {
            try {
                List list = mongoUserDao.findByName(name);
                observer.onNext(list);
                observer.onCompleted();
            } catch (Exception e) {
                e.printStackTrace();
                observer.onError(e);
            }
        });

        return ob.subscribeOn(Schedulers.io());
    }

    public Observable saveMongoUser(MongoUser mongoUser) {
        Observable ob = Observable.create(observer -> {
            try {
                MongoUser saved = mongoUserDao.save(mongoUser);
                observer.onNext(saved);
                observer.onCompleted();
            } catch (Exception e) {
                e.printStackTrace();
                observer.onError(e);
            }
        });

        return ob.subscribeOn(Schedulers.io());
    }
}

单元测试Mock MongoRepository测试UserService

1.Mock Repository

import static org.mockito.Mockito.*; // 静态导入导入Mockito的内置方法

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfig.class)
public class UserServiceMockTest {

    @InjectMocks // 将Mock的mongoUserDao注入到Service中
    @Autowired
    private UserService service;

    @Mock //Mock Repository
    private MongoUserDao mongoUserDao;

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Before
    public void setUp(){
        // 在使用@Mock注解时必须初始化Mocks
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testGetMongoUser() {}

    @Test
    public void testSaveMongoUser() {}  
}

关于上面代码的操作步骤:

# 1. mock repository对象
    @Mock //Mock Repository
    private MongoUserDao mongoUserDao;

# 2. 将mock的对象注入到service之中
    @InjectMocks // 将Mock的mongoUserDao注入到Service中
    @Autowired
    private UserService service;

# 3. 使用@Mock注解时必须初始化注解
    @Before //表示在测试方法调用前执行
    public void setUp(){
        // 初始化Mock注解
        MockitoAnnotations.initMocks(this);
    }

# 4. @Rule实现测试单元对异常的判断
    @Rule
    public ExpectedException expectedException = ExpectedException.none();  

2.编写一个基本的测试方法

@Test
public void testGetMongoUser() {
    // 1. 先初始化一个我们定义的fake的返回的集合
    List<MongoUser> list = new ArrayList<MongoUser>();
    MongoUser user = new MongoUser();
    user.setId(UUID.randomUUID().toString());
    user.setName("user");
    list.add(user);

    // stubbing mongoUserDao当执行findByName(str)时,anyString()表示传入任意一个String类型的数据
    // 就返回我们定义的fake的集合
    when(mongoUserDao.findByName(anyString())).thenReturn(list);
    // stubbing 当传入一个null参数时,抛出空指针异常
    when(mongoUserDao.findByName(null)).thenThrow(
            new NullPointerException("username cannot be null"));

    //测试service方法
    List<MongoUser> listRs = service.findMongoUserByName("user")
            .toBlocking().first();

    // 验证传入的参数是否是stubbing时matcher的参数
    verify(mongoUserDao).findByName(anyString());

    // 断言方法返回不为null
    Assert.assertNotNull(listRs);
    // 断言返回的集合是我们定义的集合
    Assert.assertTrue(listRs.containsAll(list));

    // 预言下面会抛出NullPointerException
    expectedException.expect(NullPointerException.class);
    // 预言抛出的异常信息包含 username cannot be null
    expectedException.expectMessage("username cannot be null");
    // 传入null会抛出异常
    service.findMongoUserByName(null).toBlocking().first();
}

3.测试一个保存方法,带参数匹配和返回处理

@Test
public void testSaveMongoUser() {
    // 定义一个数组保存save方法生成的id
    String[] ids = new String[1];
    // stubbing mongoUserDao当执行save方法并传入一个MongoUser对象时
    when(mongoUserDao.save(argThat(new ArgumentMatcher() {
        // 匹配传入的参数为一个MongoUser对象
        @Override
        public boolean matches(Object argument) {
            return argument instanceof MongoUser;
        }
    }))).thenAnswer(new Answer() {
         // 返回mock的保存后的MongoUser对象带ID信息,并将ID保存在ids数组中
        @Override
        public MongoUser answer(InvocationOnMock invocation)
                throws Throwable {
            MongoUser user = invocation.getArgumentAt(0, MongoUser.class);
            user.setId(ids[0] = UUID.randomUUID().toString());
            return user;
        }
    });

    //测试保存方法
    MongoUser mongoUser = new MongoUser();
    mongoUser.setName("test");
    MongoUser saved = service.saveMongoUser(mongoUser).toBlocking().first();

    //验证保存对象是否正确
    Assert.assertNotNull(saved);
    Assert.assertEquals(mongoUser.getName(), saved.getName());
    Assert.assertEquals(ids[0], saved.getId());
}

至此,通过使用mock框架,我们就可以在不使用实际配置数据源的情况下,就可以测试我们的Service处理

你可能感兴趣的:(Java)