一、简要概念:
1.Mock的概念:mock就是创建一个类的虚假的对象,在测试环境中,用来替换掉真实的对象
2.目的:
①验证这个对象的某些方法的调用情况,调用了多少次,参数是什么等等
②可以随时指定mock对象的某个方法返回什么样的值,或执行什么样的动作。
Mockito.verify(mockUserManager, Mockito.times(3)).performLogin(...);
Mockito.when(mock.verifyPassword(anyString())).thenReturn(true);
3.要使用mock,一般需要使用mock框架,目前安卓最常用的有两个,Mockito和JMockit。两者的区别是,前者不能mock static method和final class、final method,后者可以。
二、环境配置:
testCompile "org.mockito:mockito-core:1.10.19"
三、测试demo,一切尽在代码中
class LoginPresenter {
private String userName;
LoginView view = new LoginView();
public void login(String name, String pwd){
view.performLogin( name, pwd );
}
public String getUserName(){
return userName;
}
public void setUserName(String name){
this.userName = name;
}
public String getServerData (String param){
return "服务器数据";
}
public void setView( LoginView view){
this.view = view;
}
void privateMethod(String name, String pwd){
view.performLogin( name, pwd );
}
public void buttonClickCallback(){
view.setOnFcButtonClickListener(new LoginView.OnFcButtonClickListener() {
@Override
public void onFcButtonClick(int n) {
if (n == 1) {
view.performLogin("fc","111");
}
}
});
}
public class LoginView {
public interface OnFcButtonClickListener {
void onFcButtonClick(int n);
}
private OnFcButtonClickListener onfcButtonClickListener;
public void setOnFcButtonClickListener(OnFcButtonClickListener listener){
this.onfcButtonClickListener = listener;
}
public LoginView() {
}
public void performLogin(String name, String pwd){
}
public void buttonClickCallback(int n){
onfcButtonClickListener.onFcButtonClick(n);
}
}
mockito的用法的简单例子
public class LoginPresenterTest {
private LoginView mockLoginView;
private LoginPresenter presenter;
@Before
public void setUp() throws Exception {
mockLoginView = Mockito.mock(LoginView.class);
presenter = new LoginPresenter();
}
/**
* 方法描述:测试 LoginPresenter的login()方法是否调用LoginView的performLogin()方法
* 期待结果:被调用,且参数正常
*
* 注意:mock出来的对象并不会自动替换掉正式代码里面的对象,你必须要有某种方式把mock对象应用到正式代码里面
*
* @throws Exception
*/
@Test
public void login() throws Exception {
presenter = new LoginPresenter();
presenter.setView(mockLoginView);
presenter.login("fc","111");
Mockito.verify(mockLoginView).performLogin("fc","111");
// Mockito.verify(mockLoginView).performLogin("大大","111");
}
/**
* 方法描述:是否至少调用一次某个方法
* 期待结果: 是
*
* @throws Exception
*/
@Test
public void login_atLeastOnce() throws Exception {
presenter.setView(mockLoginView);
presenter.login("fc","111");
Mockito.verify(mockLoginView,Mockito.atLeastOnce()).performLogin("fc","111");
}
/**
* 方法描述:测试是否调用了两次
* 期待结果: 是
*
* @throws Exception
*/
@Test
public void login_twice() throws Exception {
presenter.setView(mockLoginView);
presenter.login("fc","111");
presenter.login("fc","111");
Mockito.verify(mockLoginView,Mockito.times(2)).performLogin("fc","111");
}
/**
* 指定mock对象的某个方法返回特定的的值
*/
@Test
public void getServerData_Specify(){
String value = "小小";
LoginPresenter mockPresenter = Mockito.mock(LoginPresenter.class);
Mockito.when(mockPresenter.getServerData(Mockito.anyString())).thenReturn(value);
Assert.assertEquals(mockPresenter.getServerData("你好"),value);
}
/**
* 调用一次返回不同的值
*/
@Test
public void getServerData_differValue(){
String value = "ZhangSan";
String secondValue = "LiSi";
LoginPresenter mockPresenter = Mockito.mock(LoginPresenter.class);
Mockito.when(mockPresenter.getServerData(Mockito.anyString())).thenReturn(value).thenReturn(secondValue);
Assert.assertEquals(mockPresenter.getServerData("你好"),value);
Assert.assertEquals(mockPresenter.getServerData("你好+1"),secondValue);
}
/**
* mock和spy 的区别:
* 使用Mock生成的类,所有方法都不是真实的方法,而且返回值都是NULL
* 使用Spy生成的类,所有方法都是真实方法,返回值都是和真实方法一样的。
*
* @throws Exception
*/
@Test
public void getUserName() throws Exception{
// LoginPresenter spyPresenter = Mockito.mock(LoginPresenter.class);
LoginPresenter spyPresenter = Mockito.spy(LoginPresenter.class);
spyPresenter.setUserName("fc");
Assert.assertEquals("fc",spyPresenter.getUserName());
}
/**
* 测试私有方法: 去掉private
*/
@Test
public void testPrivateMethod(){
presenter = new LoginPresenter();
presenter.setView(mockLoginView);
presenter.privateMethod("fc","111");
Mockito.verify(mockLoginView).performLogin("fc","111");
}
/**
* 测试接口回调,异步方法:
* 指定回调某种状态后,验证代码逻辑对不对
*/
@Test
public void testCallBack(){
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
LoginView.OnFcButtonClickListener listener = (LoginView.OnFcButtonClickListener) arguments[0];
//模拟回调的状态 可以试试把1改为其他的值
listener.onFcButtonClick(1);
return null;
}
}).when(mockLoginView).setOnFcButtonClickListener(Mockito.any(LoginView.OnFcButtonClickListener.class));
presenter.setView(mockLoginView);
presenter.buttonClickCallback();
Mockito.verify(mockLoginView).performLogin(Mockito.anyString(),Mockito.anyString());
}