2011-09-28 2 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 Test Project с этим модулем clas 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 верните строку «Это новое значение!».

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

Правильные ожидания легкая часть, но как заменить служба, объявленная в манифесте, запущенная каркасом, и весь жизненный цикл привязки с созданным вами mock-объектом: 'myServiceMock'? – TWiStErRob