基于EasyMock实现对Service组件的测试
Service组件通常用来运行后台的任务,通常被运行在一个独立的进程中,因此可以将其控制在一个独立的环境中进行测试。这需要借助于模拟对象的相关技术。
EasyMock 是一套通过简单的方法对于指定的接口或类生成 Mock 对象的类库,它能利用对接口或类的模拟来辅助单元测试。
以下基于EasyMock来实现将Service组件分离出来进行测试:
首先实现一个简单的待测应用,在主界面上有一个文本输入框,用来接收用户输入,并根据输入的类容来构造一个ReverseString类,而ReverseString类又实现了IReverse接口,最终将这个新构造的ReverseString类对象传递给Service,并调用自身的reverseStr()方法将内含的字符串反转。
IReverse代码如下:
package com.winstonwolfe.servicedemo;
import java.io.Serializable;
public interface IReverse extends Serializable{ //因为涉及到用Intent、Bundle来传递对象,所以这里需要实现序列化接口
public String reverseStr();
}
ReverseString代码如下:
package com.winstonwolfe.servicedemo;
import java.io.Serializable;
public class ReverseString implements IReverse{
private String str = "";
public ReverseString(String s){
str = s;
}
public ReverseString(){
str = "NULL";
}
@Override
public String reverseStr(){ //实现接口方法,将字符串反转
StringBuffer sb = new StringBuffer(str);
sb=sb.reverse();
return sb.toString();
}
}
MainActivity中主要代码如下:
public class MainActivity extends Activity {
private Button btn;
private EditText et;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et = (EditText)findViewById(R.id.editText1);
btn = (Button)findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intentintent = new Intent();
ReverseString rs = new ReverseString(et.getText().toString());
Bundle bundle = new Bundle();
bundle.putSerializable("obj", rs);
intent.putExtras(bundle);
intent.setClass(MainActivity.this, PrintService.class);
startService(intent);
}
});
}
待测试的Service代码如下:
public class PrintService extends Service{
public String strReversed = "";
public int onStartCommand(Intent intent, int flags, int startId){
String theStr = "";
IReverse rs = (IReverse)intent.getSerializableExtra("obj");
if(rs!=null){
fillReverseStr(rs);
Toast.makeText(PrintService.this,
strReversed,
Toast.LENGTH_LONG).show();
}
return START_NOT_STICKY;
}
public void fillReverseStr(IReverse rs){
if(rs!=null){
strReversed = rs.reverseStr();
}
else{
strReversed = "传入的字符串为空";
}
}
运行如上应用,在文本框输入字符串后,点击按钮,将会弹出一个Toast显示反转后的字符串,同时在后台会将该字符串赋值给PrintService自身的变量strReversed。
以下实现将PrintService分离出来进行测试,利用EasyMock绕过用户界面(即MainActivity)和ReverseString类,直接模拟一个IReverse接口的对象,指定该模拟对象的reverseStr()方法的返回值,然后用该模拟对象调用Service来进行测试。
新建测试项目,将EasyMock的jar包添加到libs目录,并在Build path中引用。
然后继承ServiceTestCase<PrintService>来编写测试用例,测试用例的代码如下:
package com.winstonwolfe.servicedemo.test;
import org.easymock.EasyMock;
import android.content.Intent;
import android.test.ServiceTestCase;
import com.winstonwolfe.servicedemo.PrintService;
import com.winstonwolfe.servicedemo.IReverse;
public class testCaseOfService extendsServiceTestCase<PrintService> {
public testCaseOfService() {
super(PrintService.class);
}
public void testServiceWithEasyMock() throws InterruptedException{
Intent intent = new Intent();
intent.setClass(getContext(),PrintService.class);
startService(intent);
PrintService service =(PrintService)getService();
final IReverse rs = EasyMock.createMock(IReverse.class); //创建一个IReverse接口的模拟对象
EasyMock.expect(rs.reverseStr()).andReturn("TEST").atLeastOnce();//期望rs这个模拟对象的reverseStr()方法将被调用至少一次,并且这里指定返回的字符串值
EasyMock.replay(rs); //开始模拟过程
service.fillReverseStr(rs); //用模拟对象rs来调用Service的对象
Thread.sleep(2000);
assertEquals("TEST", service.strReversed);
EasyMock.verify(rs); //断言模拟对象的方法调用满足期望条件
}
}