Reasons for use
In a unit test, mock objects can simulate the behavior of complex, real objects and are therefore useful when a real object is impractical or impossible to incorporate into a unit test. If an actual object has any of the following characteristics, it may be useful to use a mock object in its place.
If the real object:
- supplies non-deterministic results (e.g., the current time or the current temperature);
- has states that are difficult to create or reproduce (e.g., a network error);
- is slow (e.g., a complete database, which would have to be initialized before the test);
- does not yet exist or may change behavior;
- would have to include information and methods exclusively for testing purposes (and not for its actual task).
For example, an alarm clock program which causes a bell to ring at a certain time might get the current time from the outside world. To test this, the test must wait until the alarm time to know whether it has rung the bell correctly. If a mock object is used in place of the real object, it can be programmed to provide the bell-ringing time (whether it is actually that time or not) so that the alarm clock program can be tested in isolation.
[Wikipedia]There are several mock testing framework in java, such as JMock, EasyMock, Mockito... It seems that Mockito is the best choice or most popular for now (for some reasons)
So, I'd like to give an example of Mockito.
Add Dependency of Mockito to POM.XML
<groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> <scope>test</scope>Create a test class with Mockito, TestNG and Fest Assertion
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
/**
* Created by nhien.truong on 3/3/14.
*/
public class TestMockito {
//creating a mock object
@Mock List childrenList;
// just for data
String[] myChildrenNames;
@BeforeMethod
public void beforeTest(){
/**
* Initializing data.
*/
myChildrenNames = new String[]{
"Man Nhien"
,"Hao Nhien"
,"Bao Nhien"
};
MockitoAnnotations.initMocks(this);
/**
* Stubbing the methods.
* To override the original one.
*/
when(childrenList.get(anyInt())) // call with any int value
.thenReturn(myChildrenNames[0]) // The first call will return my first child
.thenReturn(myChildrenNames[1]) // The second call will return my next child
.thenReturn(myChildrenNames[2]) // The third call will return my last child
.thenThrow(NoMoreChildException.class);// Oh man, I don't have any more child.
}
/**
* Expected result: return correct children names
*/
@Test
public void testValidChildren(){
Random random = new Random();
assertThat(childrenList.get(random.nextInt()))
.isEqualTo(myChildrenNames[0]);
assertThat(childrenList.get(random.nextInt()))
.isEqualTo(myChildrenNames[1]);
assertThat(childrenList.get(random.nextInt()))
.isEqualTo(myChildrenNames[2]);
}
/**
* Expect this test will throw exception
*/
@Test//(expectedExceptions = {NoMoreChildException.class})
public void testInvalidChildren(){
for(int i=0;i<5;i++)
childrenList.get(i);
}
}
class NoMoreChildException extends Exception{
}
As you guessed, the last test method will be failed. In order to make it passed, we just remove the single comment of this line:@Test//(expectedExceptions = {NoMoreChildException.class})
Không có nhận xét nào:
Đăng nhận xét