LLT是測試系統的一部分,主要是由代碼開發人員來編寫,Mock的意思是效仿模仿的意思,就是最測試過程當中不須要的一些類和方法模擬出相應的返回值,稱爲打樁,測試關注的是一個類或方法的結果而不是過程調用,打樁涉及到不一樣的類,有返回值、無返回值、參數驗證、靜態類靜態方法、final方法等不一樣的方式。數據庫
流行的Mock工具如jMock、EsayMock、Mockito等不能mock靜態、final、私有方法函數
PowerMock中的註釋工具
1. 程序運行順序註釋測試
1)Test將一個普通的方法裝飾成爲一個測試方法spa
2)@BeforeClass 它會在全部的方法運行以前進行執行,static修飾code
3)@AfterClass 它會在全部的方法運行結束以後進行執行,static修飾對象
4)@Before 會在每一個測試方法運行以前執行一次blog
5)@After 會在每一個測試方法運行以後執行一次開發
其中@Before @Test @After 這三個標籤是組成執行的。有幾個@Test,就會執行多少次。get
2. 其餘運行註解
1)@RunWith 能夠修改測試運行期 org.junit.runner.Runner,當須要mock私有方法調用的私有方法是,須要加上@RunWith(PowerMockRunner.class)
2)@PrepareForTest 在使用mock是,首先要在該項添加mock的類@PrepareForTest({類名.class})
@PrepareForTest 註解和@RunWith註解是結合使用的,不要用單獨使用它們中的任何一個,不然不起做用,當使用PowerMock和去mock靜態,final或者私有方法時,須要機上兩個註解。
經常使用的Mock方法:
1.Mock普通對象(有返回值)
1 public class Calculator{ 2 public int Add(int a, int b){ 3 return a + b; 4 } 5 }
Mock方法以下(這裏不須要添加PrepareForTest 和RunWith註解)
1 @Test 2 public void testAdd(){ 3 Calculator calculator = PowerMockito.mock(Calculator.class); 4 PowerMockito.when(calculator.Add(Mockito.anyInt(), Mockito.anyInt())).thenReturn(10); 5 assertEquals(10, calculator.Add(1, 1)); 6 }
2. Mock普通對象(無返回值)
1 public class Calculator{ 2 public void print(){ 3 System.out.println("Hello World"); 4 } 5 }
Mock方法以下(這裏不須要添加PrepareForTest 和RunWith註解)
1 @Test 2 public void testPrint(){ 3 Calculator calculator = PowerMockito.mock(Calculator.class); 4 PowerMockito.doNothing().when(calculator).print(); 5 calculator.print(); 6 //驗證Mock對象被調用 7 Mockito.verify(calculator).print(); 8 }
3. Mock靜態方法
1 public class ClassThatContainsStaticMethod(){ 2 public static String getUserName(int id){ 3 String string = "UserName" + id; 4 return string; 5 } 6 }
Mock方法以下(這裏不須要添加PrepareForTest 和RunWith註解)
1 @RunWith(PowerMockito.class) 2 @PreparaForTest(ClassThatContainsStaticMethod.class) 3 pulic class testClassThatContainsstaticMethod{ 4 @Test 5 public void testGetUserName() throws Exception{ 6 PowerMockito.mockStatic(ClassThatContainsStaticMethod.class); 7 PowerMockito.when(ClassThatContainsStaticMethod.getUserName(Mockito.anyInt())).thenReturn(null); 8 assertEquals(ClassThatContainsStaticMethod.getUserName(123), null); 9 } 10 }
4. Mock私有方法
使用PowerMockito.method獲取Method對象調用私有方法,除此以外,還有Whitebox.InvokeMethod直接調用,在此不作說明;
1 public class Calculator{ 2 private int addPrivate(int a, int b){ 3 return a + b; 4 } 5 }
Mock方法以下:
1 @Test 2 public void testAddPrivate() throws Exception{ 3 Calculator calculator = PowerMockito.mock(Calculator.class); 4 PowerMockito.when(calculator, "addPrivate", Mockito.anyInt(), Mockito.anyInt).thenReturn(10); 5 6 Method method = PowerMockito.method(Calculator.class, "addPrivate", int.class, int.class); 7 int result = (Integer) method.invoke(calculator, 1,1); 8 assertEquals(10, result) 9 }
5. Mock final類或者方法
1 public final class Calculator{ 2 public final int add(int a, int b){ 3 return a + b; 4 } 5 public final void addVoid(int a, int b){ 6 System.out.println(a + b); 7 } 8 }
Mock方法以下:
1 @RunWith(PowerMockito.class) 2 @PreparaForTest(Calculator.class) 3 public class CalculatorTest{ 4 @Test 5 public void testAdd(){ 6 Calculator calculator PowerMockito.mock(Calculator.class); 7 PowerMockito.when(calculator.add(Mockito.anyInt(), Mockito.anyInt())).thenReturn(10); 8 int result = calculator.add(1,1); 9 assertEquals(result, 10); 10 } 11 @Test 12 public void testAddVoid(){ 13 Calculator calculator = PowerMockito.mock(Calculator.class); 14 PowerMockito.doNothing().when(calculator).addVoid(Mockito.anyInt(), Mockito.anyInt()); 15 calculator.addVoid(100,100); 16 Mockito.verify(calculator).addVoid(100,100); 17 } 18 }
6. Mock構造函數
類一:
1 public class ClassUnderTest(){ 2 public boolean callFinalMethod(){ 3 ClassDependency classDependency = new ClassDependency(); 4 return classDependency.isAlive(); 5 } 6 }
類二:
1 public class ClassDependency{ 2 public final boolean isAlive(){ 3 return false; 4 } 5 }
Mock方法以下(whenNew建立對象是若不成功(如無對應構造函數))會拋出異常,講義在test塊拋出異常而不是用try。。。catch捕獲,這樣方便問題定位。
@RunWith(PowerMockito.class) @PreparaForTest({ClassUnderTest.class, ClassDependency.class}) public class TestClassUnderTest{ @Test public void testCallFinalMethod() throws Exception{ ClassDependency dependency = PowerMockito.mock(ClassDependency.class); //該項建立可能會拋出異常 PowerMockito.whenNew(ClassDependency.class).withNoArguments().thenReturn(dependency); ClassUnderTest classUnderTest = new ClassUnderTest(); Assert.assertEquals(classUnderTest.callFinalMethod()); } }
7. 反射設置變量的值
該方法主要是使用WhiteBox的setInternalState方法對變量在某個類中進行替代,模塊中代碼中常常用該方法mock掉數據庫查詢的操做。用本地化的mock數據庫操做(如查詢map對象替代)
public class ReflectObject{ private String privateStr = "str"; protected String protectedStr = "str"; private static String staticStr = "str"; public String getPrivateStr(){ return privateStr; } public String getProtectedStr(){ return protectedStr; } public static String getStaticStr(){ return staticStr; } }
Mock方法以下:
1 public class ReflectObjectTest(){ 2 @Test 3 public void testReflect() throws Exception{ 4 ReflectObject reflect = new ReflectObject(); 5 WhiteBox.setInternalState(reflect, "privateStr", "privateStr"); 6 WhiteBox.setInternalState(reflect, "protectedStr", "protectedStr"); 7 WhiteBox.setInternalState(reflect, "staticStr", "staticStr"); 8 9 assertEquals("privateStr", reflect.getPrivateStr()); 10 assertEquals("protectedStr", reflect.getProtectedStr()); 11 assertEquals("staticStr", reflect.getStaticStr()); 12 } 13 }
8. Mock靜態方法拋異常
1 public class ThrowsException{ 2 public static void throwsException() throws RuntimeException{ 3 //do nothing 4 } 5 }
Mock方法以下:
public class ThrowsException{ @Test(expected=RuntimeException.class) public void testThrowsException(){ PowerMockito.mockStatic(ThrowsException.class); PowerMockito.doThrows(new RuntimeException("Test exception")).when(ThrowsException); ThrowsException.throwsException(); } }