强大的Mockito测试框架

jopen 11年前

1自动生成Mock类

在需要Mock的属性上标记@Mock注解,然后@RunWith中配置Mockito的TestRunner或者在setUp()方法中显示调用MockitoAnnotations.initMocks(this);生成Mock类即可。

 

2自动注入Mock类到被测试类

只要在被测试类上标记@InjectMocks,Mockito就会自动将标记@Mock、@Spy等注解的属性值注入到被测试类中。

import static org.mockito.Mockito.when;     import java.util.Collections;  import java.util.List;     import javax.annotation.Resource;     import org.junit.Assert;  import org.junit.Before;  import org.junit.Test;  import org.junit.runner.RunWith;  import org.mockito.InjectMocks;  import org.mockito.Mock;  import org.mockito.MockitoAnnotations;  importorg.springframework.test.context.ContextConfiguration;  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;     import com.cdai.ssi.user.dao.UserDao;  import com.cdai.ssi.user.domain.UserDomain;  import com.cdai.ssi.user.dto.UserDto;  importcom.cdai.ssi.user.service.UserService;     @RunWith(SpringJUnit4ClassRunner.class)  @ContextConfiguration({"classpath:spring/spring-config.xml"})  public class UserServiceTest {                     @InjectMocks           @Resource(name= "userService")           privateUserService userService;                     @Mock           privateUserDao userDao;              @Before           publicvoid setUp() {                     MockitoAnnotations.initMocks(this);           }                     @Test           publicvoid testQueryAll() {                     when(userDao.selectAll()).                              thenReturn(Collections.<UserDomain>emptyList());                                         List<UserDto>dtoList = userService.queryAll();                                         Assert.assertTrue(dtoList.isEmpty());           }            }

<p>@InjectMocks的问题是:如果被测试类是代理类,那么注入会失效。比如上面的UserService如果是事务或者其他AOP代理类,那么进入@Test方法时UserService中的DAO属性不会被Mock类替换。</p>

 

3有些方法想Mock定制,有些想调用真实方法

因为@Mock针对接口生成Mock类,所以我们是没法调用到真实的实现类的方法。可以使用@Spy注解标注属性,并且标注@Resource注解让Spring注入真实实现类,那么Mockito就会自动生成Spy类。

 

例如:

         @InjectMocks

<p>@Resource(name ="userService")</p>

         privateUserService userService;

        

         @Spy

         @Resource

         privateUserDao userDao;

 

Spy类就可以满足我们的要求。如果一个方法定制了返回值或者异常,那么就会按照定制的方式被调用执行;如果一个方法没被定制,那么调用的就是真实类的方法。

 

如果我们定制了一个方法A后,再下一个测试方法中又想调用真实方法,那么只需在方法A被调用前,调用Mockito.reset(spyObject);就行了。

import static org.mockito.Mockito.when;     import org.mockito.Mockito;     public class TestMockObject implementsITestMock {              publicstatic void main(String[] args) {                                         ITestMockmock = Mockito.mock(TestMockObject.class);                     System.out.println(mock.test1());                     System.out.println(mock.test2());                                         ITestMockspy = Mockito.spy(new TestMockObject());                     System.out.println(spy.test1());                     System.out.println(spy.test2());                                         when(spy.test1()).thenReturn(100);                     System.out.println(spy.test1());                                         Mockito.reset(spy);                     System.out.println(spy.test1());                     System.out.println(spy.test2());                                         when(spy.test1()).thenReturn(104);                     System.out.println(spy.test1());           }              @Override           publicint test1() {                     System.out.print("RealTest1()!!! - ");                     return1;           }              @Override           publicint test2() {                     System.out.print("RealTest2()!!! - ");                     return2;           }     }

输出为:

0

0

Real Test1()!!! - 1

Real Test2()!!! - 2

Real Test1()!!! - 100

Real Test1()!!! - 1

Real Test2()!!! - 2

Real Test1()!!! - 104