Verifying方法調(diào)用

??在編寫單元測試的時候,需要驗(yàn)證某些信息,或者是返回結(jié)果,或者是執(zhí)行流程。一個沒有任何結(jié)果驗(yàn)證的單元測試是沒有任何意義的。對于存在返回值的方法,可以通過對返回值進(jìn)行校驗(yàn)(使用Assert),來判斷方法的邏輯正確。但是對于返回值為void的方法,或者想要校驗(yàn)?zāi)承﹎ock的方法是否被調(diào)用,此時就需要使用Verify來進(jìn)行驗(yàn)證。
??Verifying功能非常強(qiáng)大,在Mockito、PowerMockito等框架中都存在相應(yīng)的方法。它可以檢查在單元用例執(zhí)行過程中某個方法是否被執(zhí)行,Powermock提供了多種方式驗(yàn)證方法是否被調(diào)用。

一、Verify普通方法

??先來看下業(yè)務(wù)代碼。

public class User {
    public boolean isNew() {
        throw new UnsupportedOperationException();
    }

    public void update() {
        throw new UnsupportedOperationException();
    }

    public void create() {
        throw new UnsupportedOperationException();
    }
}

public class UserService {
    public void saveUser(User user) {
        if (user.isNew()) {
            user.create();
            return;
        }

        user.update();
    }
}

??業(yè)務(wù)代碼很簡單,現(xiàn)在看下測試用例:

@RunWith(PowerMockRunner.class)
public class UserServiceTest {
    @Mock
    private User userMock;

    @Test
    public void shouldCreateUserIfUserIsNew() {
        PowerMockito.when(userMock.isNew()).thenReturn(true);

        UserService userService = new UserService();
        userService.saveUser(userMock);

        // Verify方法create被調(diào)用
        Mockito.verify(userMock).create();

        // Verify方法update沒有被調(diào)用
        Mockito.verify(userMock, Mockito.never()).update();
    }
}

??此處saveUser方法是void的,可以驗(yàn)證兩個邏輯,根據(jù)isNew的返回值來verify是create被調(diào)用還是update被調(diào)用。在該單元測試用例中,isNew被mock返回值為true,所以后面驗(yàn)證create被調(diào)用,update方法沒有被調(diào)用。

二、Verify靜態(tài)方法

??現(xiàn)在再來看一個verify靜態(tài)方法的例子。業(yè)務(wù)代碼:

public class Employee {
    public static void giveIncrementOf(int percentage) {
        throw new UnsupportedOperationException();
    }
}
public class EmployeeService {
    public boolean giveIncrementToAllEmployeeOf(int percentage) {
        try {
            Employee.giveIncrementOf(percentage);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

??業(yè)務(wù)代碼是根據(jù)給定的百分比給員工漲工資,如果成功則返回true,否則出現(xiàn)異常時返回false。下面測試用例verify方法Employee.giveIncrementOf被調(diào)用。

@RunWith(PowerMockRunner.class)
@PrepareForTest({Employee.class})
public class EmployeeServiceTest {

    @Test
    public void shouldInvokeGiveIncrementOfMethod() {
        // Mock
        PowerMockito.mockStatic(Employee.class);
        PowerMockito.doNothing().when(Employee.class);
        Employee.giveIncrementOf(9);

        // Execute
        EmployeeService employeeService = new EmployeeService();
        employeeService.giveIncrementToAllEmployeeOf(9);

        // Verify
        PowerMockito.verifyStatic();
        Employee.giveIncrementOf(9);
    }
}

??首先使用verifyStatic通知Powermock現(xiàn)在需要驗(yàn)證靜態(tài)方法,然后后面跟著需要驗(yàn)證的靜態(tài)方法調(diào)用。

三、Verify方法調(diào)用順序

??有時候想要驗(yàn)證多個方法是按照一定的順序執(zhí)行,比如在測試UserService.saveuser方法時,想要確保user.isNew先被調(diào)用,然后是user.create或user.update方法被調(diào)用,測試用例可以如下實(shí)現(xiàn):

@Test
    public void shouldInvokeIsNewBeforeInvokingUpdate() {
        UserService userService = new UserService();
        userService.saveUser(userMock);

        InOrder inOrder = Mockito.inOrder(userMock);
        inOrder.verify(userMock).isNew();
        inOrder.verify(userMock).update();
        inOrder.verify(userMock, Mockito.never()).create();
    }

??從上面的用例中可以看出,想要驗(yàn)證方法的調(diào)用順序,需要以下兩點(diǎn):
??1. 首先創(chuàng)建一個InOrder實(shí)例;
??2. 使用這個實(shí)例按照給定的順序來驗(yàn)證相應(yīng)的方法。給定的方法的順序必須精確的匹配方法調(diào)用的順序,否則會執(zhí)行錯誤。

四、其他驗(yàn)證方法及模式

??Mockito和PowerMockito除了上述介紹的用法外,還提供了很多其他相關(guān)的verify方法。

//根據(jù)模式驗(yàn)證普通方法
public static <T> T verify(T mock, VerificationMode mode);
//根據(jù)模式驗(yàn)證靜態(tài)方法
public static synchronized void verifyStatic(VerificationMode verificationMode);
//驗(yàn)證一個實(shí)例的私有方法
public static PrivateMethodVerification verifyPrivate(Object object) throws Exception;
//根據(jù)模式驗(yàn)證一個實(shí)例的私有方法
public static PrivateMethodVerification verifyPrivate(Object object, VerificationMode verificationMode)  throws Exception;
//驗(yàn)證一個類的私有方法
public static PrivateMethodVerification verifyPrivate(Class<?> clazz);
//根據(jù)模式驗(yàn)證一個類的私有方法
public static PrivateMethodVerification verifyPrivate(Class<?> clazz, VerificationMode verificationMode) throws Exception;

相關(guān)模式常用的有

  • Mockito.times(int n): 精確地驗(yàn)證執(zhí)行次數(shù)
  • Mockito.atLeastOnce(): 驗(yàn)證方法至少被調(diào)用一次
  • Mockito.atLeast(int n): 驗(yàn)證方法至少被執(zhí)行的次數(shù)
  • Mockito.atMost(int n): 驗(yàn)證方法至多被執(zhí)行的次數(shù)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • 1. 預(yù)備知識 如果需要往下學(xué)習(xí),你需要先理解 Junit 框架中的單元測試。 如果你不熟悉 JUnit,請查看下...
    會飛的大象_閱讀 2,807評論 0 4
  • Instrumentation介紹 Instrumentation是個什么東西? Instrumentation測...
    打不死的小強(qiáng)qz閱讀 7,957評論 2 39
  • 我原本一直是喝白開水的,因?yàn)槲沂冀K相信,只有白開水才無毒無害。第一次喝茶也純屬偶然。清明節(jié)下午,在微信里看到一張綠...
    櫻桃與狗閱讀 707評論 0 0
  • #1 固執(zhí)的產(chǎn)生論 近日可好,見字如晤。 萬事清和,只覺這人世是虛張的人世,有些道理看不清,有些固執(zhí)還保留。反正無...
    荒予閱讀 300評論 1 9

友情鏈接更多精彩內(nèi)容