Mockito可以做哪些事情

Mockito可以做哪些事情

1.验证行为
    @Test
    public void verify_behaviour() {
        List mock = mock(List.class);
        //  使用mock对象执行操作
        mock.add(1);
        mock.clear();
        // 验证操作是否执行
        verify(mock).clear();
        verify(mock).add(1);
    }

注意:verify验证操作是否执行,并不关心顺序;但是如果需要顺序上的验证,那么就需要每操作一步就验证一步

2.模拟期望的结果
    @Test
    public void when_andReturn() {

        Iterator mock = mock(Iterator.class);
        //模拟期望的结果
        when(mock.next()).thenReturn("first").thenReturn("2_n_time").thenReturn("haha");
        //实际执行的结果
        String actual = mock.next() + "\n" + mock.next() + "\n"+"haha";
        //断言
        assertEquals("first\n2_n_time\nhaha", actual);
    }
3.模拟方法体抛出异常
    @Test(expected = RuntimeException.class)
    public void exceptionTest(){
        List mock = mock(List.class);
        // 模拟抛出异常
        doThrow(new RuntimeException()).when(mock).add(1);
        mock.add(1);
    }
4.使用注解快速模拟
    @Mock
    public Map mockMap;
    @Before
    public void setData(){
        mockMap = new HashMap();
    }

说明:使用Mock注解来创建对象,不过需要自己来new实现类;并且会有很多限制,使用时需要注意

5.参数匹配
    @Test
    public void argsMatch(){
        Map map = mock(Map.class);
        //模拟当 map put 时返回 1
        when(map.put(anyString(),anyInt())).thenReturn(1);
        map.put("2",2);
        Integer rt= 1;
        verify(map).put("2",2);
        //断言put 的返回值
        assertEquals(rt, map.put("2",2));
    }

说明:anyInt(),anyString() …可以匹配任意参数

6.期望异常
  • @Test(expected…)

    @Test注解有一个可选的参数,”expected”允许你设置一个Throwable的子类。如果你想要验证上面的canVote()方法抛出预期的异常,我们可以这样写:

    @Test(expected = IllegalArgumentException.class  )
    public void canVote_throws_IllegalArgumentException_for_zero_age() {
        Student student = new Student();
        student.canVote("0");
    }
    
  • ExpectedException

    如果要使用JUnit框架中的ExpectedException类,需要声明ExpectedException异常

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

    然后你可以使用更加简单的方式验证预期的异常

    @Test
    public void canVote_throws_IllegalArgumentException_for_zero_age() {
          Student student =   new   Student();
          thrown.expect(IllegalArgumentException.class  );
            thrown.expectMessage("your exception msg");
          student.canVote(  0  );
    }
    
7.使用 PowerMock来 mock protected 和 private 方法
@RunWith(PowerMockRunner.class)
@PrepareForTest(ComparativeActivityService.class)
@PowerMockIgnore("javax.management.*")
public class GrouponOrderServiceImplTest {


	@Before
   public void setUp() throws Exception {
        //使用反射的方式 mock protected、 private 方法,但是一般情况下是不应该 mock 这些方法的
        PowerMockito.doReturn(false).when(comparativeActivityService, ComparativeActivityService.class.getSuperclass().getDeclaredMethod("inNewSystem",long.class)).withArguments(111L);
     //此处是 mock 一个父类的 protected 方法,其他方法类似
    }
}
8.使用白盒测试
Whitebox.setInternalState(someService, "someField", new SomeField());

说明:Whitebox.setInternalState(injectObject,"fieldName", fieldObject)来为一个不能直接使用@Mock 注解来注入的属性注入一个对象

待续

tips
  1. 打桩失败;在Test层可以debug看见打桩,但是进入被测函数就发现打桩失败了

    原因:被测试类有一个final字段,并且使用了构造函数传入了此final字段;

    解决:去掉final修饰,将构造函数改为无参构造函数,使用Java注解进行注入

  2. verify校验失败:使用eq(obj)校验的时候,一个是引用地址,另一个是实际对象的值

    参考:https://stackoverflow.com/questions/25213897/test-failure-message-in-mockito-arguments-are-different-wanted

    原因:eq函数并不能区分是引用地址还是引用的对象值

    解决办法:将eq函数修改为refEq函数保证校验的都是对象的值

参考链接: https://www.cnblogs.com/Ming8006/p/6297333.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章