zoukankan      html  css  js  c++  java
  • Mockito框架入门教程(二)

    接上一篇,继续学习其它的....

    8、找出冗余的互动(即未被验证到的)

           @Test(expected = NoInteractionsWanted.class)

           public void find_redundant_interaction(){

                  List list = mock(List.class);

                  list.add(1);

                  list.add(2);

                  verify(list,times(2)).add(anyInt());

                  //检查是否有未被验证的互动行为,因为add(1)和add(2)都会被上面的anyInt()验证到,所以下面的代码会通过

                  verifyNoMoreInteractions(list);

                  List list2 = mock(List.class);

                  list2.add(1);

                  list2.add(2);

                  verify(list2).add(1);

                  //检查是否有未被验证的互动行为,因为add(2)没有被验证,所以下面的代码会失败抛出异常

                  verifyNoMoreInteractions(list2);

           }

    9、使用注解来快速模拟

    在上面的测试中我们在每个测试方法里都mock了一个List对象,为了避免重复的mock,使测试类更具有可读性,我们可以使用下面的注解方式来快速模拟对象:

           @Mock

           private List mockList;

    OK,我们再用注解的mock对象试试

           @Test

           public void shorthand(){

                  mockList.add(1);

                  verify(mockList).add(1);

           }

    运行这个测试类你会发现报错了,mock的对象为NULL,为此我们必须在基类中添加初始化mock的代码

    public class MockitoExample2 {

           @Mock

           private List mockList;

           public MockitoExample2(){

                  MockitoAnnotations.initMocks(this);

           }

           @Test

           public void shorthand(){

                  mockList.add(1);

                  verify(mockList).add(1);

           }

    }

    或者使用built-in runner:MockitoJUnitRunner

    @RunWith(MockitoJUnitRunner.class)

    public class MockitoExample2 {

           @Mock

           private List mockList;

           @Test

           public void shorthand(){

                  mockList.add(1);

                  verify(mockList).add(1);

           }

    }

    更多的注解还有@Captor,@Spy,@InjectMocks

    10、连续调用

           @Test(expected = RuntimeException.class)

           public void consecutive_calls(){

                  //模拟连续调用返回期望值,如果分开,则只有最后一个有效

                  when(mockList.get(0)).thenReturn(0);

                  when(mockList.get(0)).thenReturn(1);

                  when(mockList.get(0)).thenReturn(2);

                  when(mockList.get(1)).thenReturn(0).thenReturn(1).thenThrow(new RuntimeException());

                  assertEquals(2,mockList.get(0));

                  assertEquals(2,mockList.get(0));

                  assertEquals(0,mockList.get(1));

                  assertEquals(1,mockList.get(1));

                  //第三次或更多调用都会抛出异常

                  mockList.get(1);

           }

    11、使用回调生成期望值

           @Test

           public void answer_with_callback(){

                  //使用Answer来生成我们我们期望的返回

                  when(mockList.get(anyInt())).thenAnswer(new Answer<Object>() {

                         @Override

                         public Object answer(InvocationOnMock invocation) throws Throwable {

                                Object[] args = invocation.getArguments();

                                return "hello world:"+args[0];

                         }

                  });

                  assertEquals("hello world:0",mockList.get(0));

                  assertEquals("hello world:999",mockList.get(999));

           }

    12、监控真实对象

    使用spy来监控真实的对象,需要注意的是此时我们需要谨慎的使用when-then语句,而改用do-when语句

           @Test(expected = IndexOutOfBoundsException.class)

           public void spy_on_real_objects(){

                  List list = new LinkedList();

                  List spy = spy(list);

                  //下面预设的spy.get(0)会报错,因为会调用真实对象的get(0),所以会抛出越界异常

                  //when(spy.get(0)).thenReturn(3);

                  //使用doReturn-when可以避免when-thenReturn调用真实对象api

                  doReturn(999).when(spy).get(999);

                  //预设size()期望值

                  when(spy.size()).thenReturn(100);

                  //调用真实对象的api

                  spy.add(1);

                  spy.add(2);

                  assertEquals(100,spy.size());

                  assertEquals(1,spy.get(0));

                  assertEquals(2,spy.get(1));

                  verify(spy).add(1);

                  verify(spy).add(2);

                  assertEquals(999,spy.get(999));

                  spy.get(2);

           }

    13、修改对未预设的调用返回默认期望值

           @Test

           public void unstubbed_invocations(){

                  //mock对象使用Answer来对未预设的调用返回默认期望值

                  List mock = mock(List.class,new Answer() {

                         @Override

                         public Object answer(InvocationOnMock invocation) throws Throwable {

                                return 999;

                         }

                  });

                  //下面的get(1)没有预设,通常情况下会返回NULL,但是使用了Answer改变了默认期望值

                  assertEquals(999, mock.get(1));

                  //下面的size()没有预设,通常情况下会返回0,但是使用了Answer改变了默认期望值

                  assertEquals(999,mock.size());

           }

    14、捕获参数来进一步断言

        @Test

           public void capturing_args(){

                  PersonDao personDao = mock(PersonDao.class);

                  PersonService personService = new PersonService(personDao);

                  ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);

                  personService.update(1,"jack");

                  verify(personDao).update(argument.capture());

                  assertEquals(1,argument.getValue().getId());

                  assertEquals("jack",argument.getValue().getName());

           }

            class Person{

                  private int id;

                  private String name;

                  Person(int id, String name) {

                         this.id = id;

                         this.name = name;

                  }

                  public int getId() {

                         return id;

                  }

                  public String getName() {

                         return name;

                  }

           }

           interface PersonDao{

                  public void update(Person person);

           }

           class PersonService{

                  private PersonDao personDao;

                  PersonService(PersonDao personDao) {

                         this.personDao = personDao;

                  }

                  public void update(int id,String name){

                         personDao.update(new Person(id,name));

                  }

           }

    15、真实的部分mock

           @Test

           public void real_partial_mock(){

                  //通过spy来调用真实的api

                  List list = spy(new ArrayList());

                  assertEquals(0,list.size());

                  A a  = mock(A.class);

                  //通过thenCallRealMethod来调用真实的api

                  when(a.doSomething(anyInt())).thenCallRealMethod();

                  assertEquals(999,a.doSomething(999));

           }

           class A{

                  public int doSomething(int i){

                         return i;

                  }

           }

    16、重置mock

           @Test

           public void reset_mock(){

                  List list = mock(List.class);

                  when(list.size()).thenReturn(10);

                  list.add(1);

                  assertEquals(10,list.size());

                  //重置mock,清除所有的互动和预设

                  reset(list);

                  assertEquals(0,list.size());

           }

    生命很短,请让生活更精彩一些!
  • 相关阅读:
    Python中的类(上)
    Django REST Framework API Guide 07
    Django REST Framework API Guide 06
    Django REST Framework API Guide 05
    Django REST Framework API Guide 04
    Django REST Framework API Guide 03
    Django REST Framework API Guide 02
    Django REST Framework API Guide 01
    Django 详解 信号Signal
    Django 详解 中间件Middleware
  • 原文地址:https://www.cnblogs.com/Aaron-007/p/10441506.html
Copyright © 2011-2022 走看看