5

リモートサービスをテストするために、次のテストクラスがあります。

public class CoreServiceBasicTest extends ServiceTestCase<CoreService> implements ServiceConnection {

    /** Tag for logging */
    private final static String TAG = CoreServiceBasicTest.class.getName();

    /** Receive incoming messages */
    private final Messenger inMessenger = new Messenger(new IncomingHandler());

    /** Communicate with the service */
    private Messenger outMessenger = null;

    /** Handler of incoming messages from service */
    private static class IncomingHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            Log.d(TAG, "Incoming message");
        }
    }

    /** Constructor for service test */
    public CoreServiceBasicTest() {
        super(CoreService.class);
    }

    /** Start the service */
    @Override
    public void setUp() {

        // Mandatory
        try {
            super.setUp();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Start the service
        Intent service = new Intent();
        service.setClass(this.getContext(), CoreService.class);
        startService(service);
        Log.d(TAG, "Service started");
    }

    public void onServiceConnected(ComponentName className, IBinder service) {
        outMessenger = new Messenger(service);
        Log.d(TAG, "Service attached");
    }

    public void onServiceDisconnected(ComponentName className) {
        // TODO Auto-generated method stub

    }

    @SmallTest
    public void testBindService() {
        // Bind to the service
        Intent service = new Intent();
        service.setClass(getContext(), CoreService.class);
        boolean isBound = getContext().bindService(service, this, Context.BIND_AUTO_CREATE);
        assertTrue(isBound);
    }
}

問題は、setUp() メソッドの startService(service) がサービスを正しく起動しないことです。これは、AVD が示すものです。

ここに画像の説明を入力

ご覧のとおり、プロセスは起動されていますが、サービスは起動されていません。その後testBindService()assertTrue(isBound)失敗します。

アクティビティからサービスを起動すると、これは起こりません:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Start the Core service
    Intent service = new Intent();
    service.setClass(this, CoreService.class);

    if (startService(service) == null) {
        Toast.makeText(this, "Error starting service!", Toast.LENGTH_LONG).show();
        Log.e(TAG, "Error starting service");
    } else {
        Toast.makeText(this, "Service started sucessfully", Toast.LENGTH_LONG).show();
    }

    // Die
    finish();
}

ここでは、以下に示すように、サービスが正しく開始されています。

ここに画像の説明を入力

Messenger を使用して Android テスト プロジェクトのアクティビティと通信するリモート サービスを開始してバインドするにはどうすればよいですか?

4

2 に答える 2

11

Androidテストプロジェクト(test.apk)の要点は、アプリケーションプロジェクト(app.apk)をインストルメント化し、アプリケーションプロジェクトに関連付けられているAndroidコンポーネント(アクティビティ、サービスなど)をユニットテストすることです。 app.apk内で作成および操作されるアクティビティとサービスをテストします。

テストプロジェクトのServiceTestCase実装内で、MessengerService実装を部分的に(Messenger、IncomingHandlerなど)2回作成しないでください。MessengerServiceの実装は、アプリケーションプロジェクトのCoreService.javaファイルに1回だけ書き込む必要があります。

ServiceConnectionは、アクティビティとサービス間の相互通信に使用されます。ここではServiceTestCaseを使用するため(単体テストサービスを意味し、他のコンポーネントとの通信は対象外であるため、考慮されません)、ServiceConnectionの実装は必要ありません。ServiceConnectionが行う唯一のことは、サービスが適切に作成されたら後で使用できるように、ソリッドMessengerオブジェクトを初期化することです。

public void onServiceConnected(ComponentName className, IBinder service) {
  // This is what we want, we will call this manually in our TestCase, after calling
  // ServiceTestCase.bindService() and return the IBinder, check out code sample below.
  mService = new Messenger(service);
}

また、この場合、ServiceTestCase.startService()を呼び出す必要はないことに注意してください。これは、ServiceTestCase.bindService()がサービスを適切に開始し(まだ開始されていない場合)、Messengerの初期化に使用する必要のあるIBinderオブジェクトを返すためです。後でオブジェクト。

CoreService.javaのIncomingHandler.handleMessage()の実装が次のようになっている場合は次のようになります。

... ...

switch (msg.what) {
  case MSG_SAY_HELLO:
    msgReceived = true;
    break;

... ...

ServiceTestCaseでメッセージ送信機能をテストするには:

... ...

IBinder messengerBinder = null;

@Override
public void setUp() throws Exception {
  super.setUp();
  // Bind the service and get a IBinder:
  messengerBinder = bindService(new Intent(this.getContext(), CoreService.class));
  //log service starting
  Log.d(TAG, "Service started and bound");
}

public void testSendMessage() {
  // Use IBinder create your Messenger, exactly what we did in ServiceConnection callback method:
  Messenger messenger = new Messenger(messengerBinder);
  Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
  messenger.send(msg);
  // Do some assert stuff here
  ... ...
}

... ...

アクティビティとサービス間の通信をテストする場合、この場合、ServiceTestCaseは適していません。ActivityInstrumentationTestCase2を使用して、実際のアクティビティをテストすることを検討してください(CoreServiceにバインドされているため、サービス機能を間接的にテストできます。

于 2012-07-09T23:06:03.650 に答える
7

ServiceTestCaseのドキュメントを見るだけで、テスト フレームワークは、テスト メソッドの 1 つがorを呼び出すまでサービスの開始を遅らせると書かれています。ServiceTestCase.startService()ServiceTestCase.bindService()

テストメソッドではなく、ServiceTestCase.startService()メソッドsetUp()で呼び出すコードを見てください。これはまだサービスを開始しません。テストメソッドの 1 つがorを呼び出すのを待っています。ServiceTestCase.startService()ServiceTestCase.bindService()

テスト メソッドtestBindService()は を呼び出していません。ServiceTestCase.bindService()代わりに、呼び出しContext.bindService()て失敗しています。テスト フレームワークはまだ待機しているため、サービスは開始されません。

リンクされた開発者ドキュメントのライフサイクル サポートの議論をもう一度見てください。

于 2012-07-09T20:27:05.420 に答える