Mocking-Mockito
Mockito allows you to stub method calls and verify interactions with objects.
When we write unit tests, we need to think of testing a certain component in isolation. We should not test anything beyond what that class’ responsibility is. Mockito helps us achieve this separation.
see:
see:
good:
1.
repositories { jcenter() }
dependencies { testCompile "org.mockito:mockito-core:1.+" }
2.
MockitoAnnotations.initMocks(this);
3.mock and InjectMocks
mock :is the object that you want to mock,will mock all the method in the object
spy:create a onjetc,and mock only some method.
InjectMocks :the object that contain mock,no need to create a object
4.when----than run
public interface CalculatorService {
public double add(double input1, double input2);
public double subtract(double input1, double input2);
public double multiply(double input1, double input2);
public double divide(double input1, double input2);
}
|
public class MathApplication {
private CalculatorService calcService;
/* public void setCalculatorService(CalculatorService calcService){
this.calcService = calcService;
}*/
public double add(double input1, double input2){
return calcService.add(input1, input2);
// return input1 + input2;
}
public double subtract(double input1, double input2){
return calcService.subtract(input1, input2);
}
public double multiply(double input1, double input2){
return calcService.multiply(input1, input2);
}
public double divide(double input1, double input2){
return calcService.divide(input1, input2);
}
}
|
public class PortfolioTester {
@InjectMocks
MathApplication matApplication;
@Mock
CalculatorService calculatorService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
// matApplication = new MathApplication();
}
@Test
public void testAdd() {
when(calculatorService.add(10,20)).thenReturn(30d);
Assert.assertEquals(30d,matApplication.add(10,20),0);
verify(calculatorService).add(10,20);
}
}
|
5.verify()
check 一個mock的action有無executr with specific 參數
6. verify,check the method execute run at pecific time
use with time ,never function
@Test
public void testAdd() {
matApplication.i=1;
when(calculatorService.add(10,20)).thenReturn(30d);
//add the behavior of calc service to subtract two numbers
when(calculatorService.subtract(20.0,10.0)).thenReturn(10.00);
when(calculatorService.subtract(20.0,10.0)).thenReturn(10.00);
//test the add functionality
Assert.assertEquals(matApplication.add(10.0, 20.0),30.0,0);
Assert.assertEquals(matApplication.add(10.0, 20.0),30.0,0);
Assert.assertEquals(matApplication.add(10.0, 20.0),30.0,0);
//test the subtract functionality
Assert.assertEquals(matApplication.subtract(20.0, 10.0),10.0,0.0);
//default call count is 1
verify(calculatorService).subtract(20.0, 10.0);
//check if add function is called three times
verify(calculatorService, times(3)).add(10.0, 20.0);
//verify that method was never called on a mock
verify(calculatorService, never()).multiply(10.0,20.0);
}
|
7. atLeast (int min) − expects min calls.
atLeastOnce () − expects at least one call.
atMost (int max) − expects max calls.
same above
8.Exception Handling
make some Exception when some mehod run
when(calculatorService.add(10.0,20.0)).thenReturn(30d);
doThrow(new RuntimeException("Add operation not implemented"))
.when(calculatorService).add(10.0,20.0);
//test the add functionality
Assert.assertEquals(matApplication.add(10.0, 20.0),30.0,0);
|
9.createn mock
Mockito provides various methods to create mock objects.
calcService = mock(CalculatorService.class);
10.ensure the oder of the method
//add the behavior to add numbers
when(calculatorService.add(20.0, 10.0)).thenReturn(30.0);
//subtract the behavior to subtract numbers
when(calculatorService.subtract(20.0, 10.0)).thenReturn(10.0);
//test the add functionality
Assert.assertEquals(calculatorService.add(20.0, 10.0), 30.0, 0);
//test the subtract functionality
Assert.assertEquals(matApplication.subtract(20.0, 10.0), 10.0, 0);
//create an inOrder verifier for a single mock
InOrder inOrder = inOrder(calculatorService);
//following will make sure that add is first called then subtract is called.
inOrder.verify(calculatorService).add(20.0, 10.0);
inOrder.verify(calculatorService).subtract(20.0, 10.0);
|
11.spy_use the real object to mock
when to use spy?
當有一real object ,我們想mock 他其中一些方法,就用spy
private class Calculator implements CalculatorService{
@Override
public double add(double input1, double input2) {
return input1+input2;
}
@Override
public double subtract(double input1, double input2) {
throw new UnsupportedOperationException("Method not implemented yet!");
}
@Override
public double multiply(double input1, double input2) {
throw new UnsupportedOperationException("Method not implemented yet!");
}
@Override
public double divide(double input1, double input2) {
throw new UnsupportedOperationException("Method not implemented yet!");
}
}
|
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mathApplication=new MathApplication();
calc=spy(new Calculator());
mathApplication.setCalculatorService(calc);
}
|
@Test
public void testAdd() {
when(calc.add(10,10)).thenReturn(30d);
doReturn(0d).when(calc).subtract(10,10);
Assert.assertEquals(30d,mathApplication.add(10,10),0);
Assert.assertEquals(0d,mathApplication.subtract(10,10),0);
}
|
although the real method is 10+10 return 20,but we can mock it return 30
need to use doReturn because the subtract method not finish,use when will throw new UnsupportedOperationException("Method not implemented yet!");
12 reset the mock
public class PortfolioTester {
@Mock
CalculatorService cs;
@InjectMocks
private MathApplication mathApplication;
@Before
public void setup() {
mathApplication = new MathApplication();
MockitoAnnotations.initMocks(this);
}
@Test
public void testAdd() {
when(mathApplication.add(10, 10)).thenReturn(20d);
Assert.assertEquals(20d, mathApplication.add(10, 10), 0);
reset(cs);
Assert.assertEquals(20d, mathApplication.add(10, 10), 0);
}
}
|
after reset,the effect of when(mathApplication.add(10, 10)).thenReturn(20d); disappear.
13Mockito - Behavior Driven Developmen
//Given
given(calcService.add(20.0,10.0)).willReturn(30.0);
//when
double result = calcService.add(20.0,10.0);
//then
Assert.assertEquals(result,30.0,0);
|
14 Advanced Topic - ArgumentCaptor
We have already set up the NotesPresenterTest with a mocked notes repository and view.
We have defined an ArgumentCaptor that captures parameters - we are using it to capture the callback for the NotesRepository when data is loaded by the presenter, so we can call it ourselves to simulate that the notes have been loaded already.
example
want to test this
@Override
public void loadNotes(boolean forceUpdate) {
// mNotesView.setProgressIndicator(true);
// if (forceUpdate) {
// mNotesRepository.refreshData();
// }
//
// // The network request might be handled in a different thread so make sure Espresso knows
// // that the app is busy until the response is handled.
// EspressoIdlingResource.increment(); // App is busy until further notice
//
// mNotesRepository.getNotes(new NotesRepository.LoadNotesCallback() {
// @Override
// public void onNotesLoaded(List<Note> notes) {
// EspressoIdlingResource.decrement(); // Set app as idle.
// mNotesView.setProgressIndicator(false);
// mNotesView.showNotes(notes);
// }
// });
}
|
@Captor
private ArgumentCaptor<LoadNotesCallback> mLoadNotesCallbackCaptor;
// Callback is captured and invoked with stubbed notes
verify(mNotesRepository).getNotes(mLoadNotesCallbackCaptor.capture());
mLoadNotesCallbackCaptor.getValue().onNotesLoaded(NOTES);
//
// // Then progress indicator is hidden and notes are shown in UI
verify(mNotesView).setProgressIndicator(false);
verify(mNotesView).showNotes(NOTES);
|
Power mock
Mockito不支持final方法,私有方法,静态方法,而PowerMock支持。所以这里也要介绍一下。但是还是不建议项目中使用,如果需要使用PowerMock才能测试,说明代码的可测试性不好,需要改进代码。一般都是历史遗留代码或者第三方库相关测试的时候才需要使用。
testCompile("org.powermock:powermock-module-junit4:1.6.2")
testCompile("org.powermock:powermock-api-mockito:1.6.2")
public class Service {
public static final String testStaticFinal() {
System.out.println("testStaticFinal");
return "static final";
}
private String testPrivate() {
System.out.println("testPrivate");
return "private";
}
public String testPrivateForPublic() {
System.out.println("testPrivateForPublic");
return testPrivate();
}
private String testPrivateWithArg(String arg) {
System.out.println("testPrivateWithArg");
return arg + "x";
}
}
|
@RunWith(PowerMockRunner.class)
@PrepareForTest( { Service.class })
public class TestService {
@Before
public void initMocks() {
mockStatic(Service.class);
}
@Test
public void testTestStaticFinal() throws Exception {
PowerMockito.when(Service.testStaticFinal()).thenReturn("mock1");
assertEquals("mock1", Service.testStaticFinal());
}
@Test
public void testPrivate() throws Exception {
Service t = mock(Service.class);
PowerMockito.when(t, "testPrivate").thenReturn("xxx");
doCallRealMethod().when(t).testPrivateForPublic();
assertEquals("xxx", t.testPrivateForPublic());
}
@Test
public void testTestPrivateWithArg() throws Exception {
Service t = spy(new Service());
String arg = "dd";
PowerMockito.when(t, "testPrivateWithArg", arg).thenReturn("lhc");
assertEquals("lhc", t.getTestPrivateWithArg(arg));
}
}
|