強大的Mockito測試框架

jopen 11年前發布 | 24K 次閱讀 Mockito 單元測試

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());
         }

}

@InjectMocks的問題是:如果被測試類是代理類,那么注入會失效。比如上面的UserService如果是事務或者其他AOP代理類,那么進入@Test方法時UserService中的DAO屬性不會被Mock類替換。

 

3有些方法想Mock定制,有些想調用真實方法

因為@Mock針對接口生成Mock類,所以我們是沒法調用到真實的實現類的方法。可以使用@Spy注解標注屬性,并且標注@Resource注解讓Spring注入真實實現類,那么Mockito就會自動生成Spy類。

 

例如:

         @InjectMocks

@Resource(name ="userService")

         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

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!