1. 程式人生 > >用JMockit寫單元測試

用JMockit寫單元測試

文字介紹:

Mock 測試是一種常見的測試方法。通常在執行測試的時候,測試程式碼往往需要與一些真實物件進行互動,又或者被測程式碼的執行需要依賴真實物件的功能。此時,我們可以使用一個輕量級的、可控制的Mock物件來取代真實物件,模擬真實物件的行為和功能,從而方便我們測試。jMock便是這種方法的一種實現。

JMock 是一個利用Mock物件來測試Java程式碼的輕量級測試工具。毫不例外,它也是xUnit家族的一員,因為它從JUnit發展而來,是JUnit的一個增強庫。jMock用法簡單,易於掌握。利用它,我們可以很容易地快速構造出所需的Mock物件,從而得以方便快捷地編寫單元測試程式碼,很適合測試驅動開發的流暢進行。

我遇到的例子,上程式碼:

public class InnerCustomerInfoServiceTest extends BaseServiceTest {
    
    @SpringBeanByType
    InnerCustomerInfoService innerCustomerInfoService;//由spring bean注入介面的實現類
    
    //...
    
    
    
    /**
     * 引數對應返回為NULL的邏輯判斷
     */
    @Test
    public void test1_FindCustomerInfo() {
        new MockUp<IbatisCustomerInfoDAO>() {//說明1
            @Mock
            CustomerInfoDO findCustomerInfo(long customerId) {
                want.number(customerId).isEqualTo(2);
                return null;
            }
        };

        CustomerInfoDO entity = innerCustomerInfoService.findCustomerInfo(2);//此處的方法呼叫程式碼,見說明1
        Assert.assertTrue(entity == null);
    }
    
    
    /**
     * 第一次就正確找到引數對應的值的邏輯測試
     */
    @Test
    public void test2_findCustomerInfoByKpId() {

        new MockUp<IbatisCustomerInfoDAO>() {
            @Mock
            CustomerInfoDO findCustomerInfoByKpId(long kpId) {
                want.number(kpId).isEqualTo(1);
                CustomerInfoDO tmpDO = new CustomerInfoDO();
                tmpDO.setCustomerRank(2);
                return tmpDO;
            }
        };

        CustomerInfoDO entity = innerCustomerInfoService.findCustomerInfoByKpId(1);
        want.number(entity.getCustomerRank()).isEqualTo(2);//說明2
    }
    
    
    /**
     * 第一次沒找到對應值 補全後正確找到引數對應的值的邏輯測試
     */
    @Test
    public void test3_findCustomerInfoByKpId() {
        new MockUp<IbatisCustomerInfoDAO>() {
            @Mock
            CustomerInfoDO findCustomerInfoByKpId(long kpId) {
                want.number(kpId).isEqualTo(1);
                return null;
            }
        };

        new MockUp<InnerCustomerInfoServiceImpl>() {//說明3
            @Mock
            CustomerInfoDO createNewCustomerInfoByKpId(long kpId) {
                want.number(kpId).isEqualTo(1);
                CustomerInfoDO tmpDO = new CustomerInfoDO();
                tmpDO.setCustomerRank(2);
                return tmpDO;
            }
        };

        CustomerInfoDO entity = innerCustomerInfoService.findCustomerInfoByKpId(1);
        want.number(entity.getCustomerRank()).isEqualTo(2);
    }
   
    //...
}


說明:

1. new MockUp<IbatisCustomerInfoDAO>,為什麼是IbatisCustomerInfoDAO?說明需要模擬IbatisCustomerInfoDAO這個物件。方法呼叫的程式碼實現:

public class InnerCustomerInfoServiceImpl implements InnerCustomerInfoService {
    private static final Log       log = LogFactory.getLog(InnerCustomerInfoServiceImpl.class);

    @Autowired
    private CustomerInfoDAO        customerInfoDAO;

    
    @Override
    public CustomerInfoDO findCustomerInfo(long customerId) {
        if (customerId <= 0) {
            log.error("param error,customerId is: " + customerId);
            return null;
        }

        return customerInfoDAO.findCustomerInfo(customerId);//此處用到了CustomerInfoDAO介面物件,故需要進行模擬,
                                                            //說明1模擬了其實現類IbatisCustomerInfoDAO的物件
    }
    //...
}

2. want的意思?想想上面的Assert.assertTrue..

3. 兩個mock?說明用到了兩個物件,需要模擬兩個物件。具體程式碼和說明1雷同。其實很簡單,照葫蘆畫瓢即可!

4.關於使用JMock需要匯入的Jar包?本例中已經由Maven同一配置管理了,在jtester裡,pom.xm相關部分如下圖:

			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>4.10</version>
			</dependency>
			<dependency>
				<groupId>com.NB.jtester</groupId>
				<artifactId>jtester.junit</artifactId>
				<version>${jtester_version}</version>
			</dependency>
			<dependency>
				<groupId>com.NB.jtester</groupId>
				<artifactId>jtester.integrated</artifactId>
				<version>${jtester_version}</version>
			</dependency>
			<dependency>
				<groupId>com.NB.jtester</groupId>
				<artifactId>jtester.spec</artifactId>
				<version>${jtester_version}</version>
			</dependency>

官方地址: