2011-09-28 100 views
8

我想为我的android应用程序编写单元测试,我想模拟我的服务类。我想测试服务中的一些错误行为,例如连接错误或未找到的文件。在单元测试下可以模拟android服务吗?

为了简化我的问题,我开始了一个新的Android项目,并创建了一个活动和服务类:

MyAndroidProjectActivity.java

package br.org.venturus.android; 

import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.view.View; 
import android.widget.TextView; 
import br.org.venturus.android.service.MyService; 

public class MyAndroidProjectActivity extends Activity { 
    private MyService service; 
    private ServiceConnection mConnection = new ServiceConnection() { 

     public void onServiceConnected(ComponentName className, IBinder binder) { 
      service = ((MyService.MyBinder) binder).getService(); 

     } 

     public void onServiceDisconnected(ComponentName className) { 
      service = null; 
     } 
    }; 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     { 
      Intent service = new Intent(this, MyService.class); 
      startService(service); 

      bindService(service, mConnection, Context.BIND_AUTO_CREATE); 
     } 

    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     // stop MyService 
     { 
      Intent svc = new Intent(this, MyService.class); 
      stopService(svc); 
     } 
    } 

    public void doChange(View view) { 
     TextView tv = (TextView) findViewById(R.id.tvHello); 

     tv.setText(service.getNewString()); 
    } 
} 

MyService.java

package br.org.venturus.android.service; 

import br.org.venturus.android.R; 
import android.app.Service; 
import android.content.Intent; 
import android.os.Binder; 
import android.os.IBinder; 

public class MyService extends Service { 

    private IBinder binder; 

    public MyService() { 
     this.binder = new MyBinder(); 
    } 
    @Override 
    public IBinder onBind(Intent intent) { 
     return binder; 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 

    } 

    public class MyBinder extends Binder { 
     public MyService getService() { 
      return MyService.this; 
     } 
    } 

    public String getNewString() { 
     return getString(R.string.change); 
    } 

} 

我用这个单元创建了一个新的Android测试项目S:

MyAndroidProjectActivityTest.java

package br.org.venturus.android.test; 

import android.test.ActivityInstrumentationTestCase2; 
import android.test.UiThreadTest; 
import android.widget.Button; 
import android.widget.TextView; 
import br.org.venturus.android.MyAndroidProjectActivity; 
import br.org.venturus.android.R; 

public class MyAndroidProjectActivityTest extends 
     ActivityInstrumentationTestCase2<MyAndroidProjectActivity> { 

    private MyAndroidProjectActivity mActivity; 
    private TextView tvHello; 
    private Button btChange; 

    public MyAndroidProjectActivityTest() { 
     super("br.org.venturus.android", MyAndroidProjectActivity.class); 
    } 

    @Override 
    protected void setUp() throws Exception { 
     super.setUp(); 

     // Get the activity and components 
     { 
      mActivity = this.getActivity(); 
      tvHello = (TextView) mActivity 
        .findViewById(br.org.venturus.android.R.id.tvHello); 
      btChange = (Button) mActivity 
        .findViewById(br.org.venturus.android.R.id.btChange); 
     } 

    } 

    public void testPreconditions() { 
     assertNotNull(tvHello); 
     assertNotNull(btChange); 
    } 

    @UiThreadTest 
    public void testChangeButton() { 
     assertEquals(tvHello.getText(), getActivity().getString(R.string.hello)); 
     btChange.performClick(); 
     assertEquals(tvHello.getText(), getActivity() 
       .getString(R.string.change)); 
    } 
} 

当运行单元测试中,预条件和改变按钮测试是细。例如,我想要做的是创建一个MyServiceMock并覆盖MyService.getNewString以返回其他值,并在测试中模拟此对象。

事情是这样的:

MyServiceMock.java

package br.org.venturus.android.test.service; 

import br.org.venturus.android.service.MyService; 

public class MyServiceMock extends MyService { 
    @Override 
    public String getNewString() {  
     return "This is the new value!"; 
    } 
} 

这可能吗?

回答

3

是的,这是可能的,我认为上面的MyServiceMock.java的例子也是一种替代方案。

有几个模拟框架可以用于此目的。

我对Mockito有一些经验。

您可以模拟MyService类并指定调用getNewString方法时返回一个字符串“This is the new value!”。

MyService myServiceMock = Mockito.mock(MyService.class); 

Mockito.doReturn("This is the new value!").when(myServiceMock).getNewString(); 

您还可以使用Mockito.doThrow()方法抛出异常时,模拟方法被称为:

Mockito.doThrow(new RuntimeException()).when(mockedList).clear(); 

//following throws RuntimeException: 
mockedList.clear(); 
+1

设定的期望是比较容易的部分,但你如何更换在框架中启动的清单中声明的​​服务以及您创建的模拟对象的所有绑定生命周期:myServiceMock? – TWiStErRob

相关问题