2012-07-06 35 views
5

Tôi có lớp thử nghiệm này để thử nghiệm một dịch vụ từ xa:Android dịch vụ không đưa ra bởi kiểm tra JUnit

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); 
    } 
} 

Vấn đề là startService (dịch vụ) trong phương pháp thiết lập() không khởi động dịch vụ một cách chính xác. Đây là những gì AVD cho thấy:

enter image description here

Như bạn thấy, quá trình này được đưa ra nhưng dịch vụ thì không. Sau đó, trên testBindService(), assertTrue(isBound) không thành công.

này không xảy ra nếu tôi khởi động dịch vụ từ một Hoạt động:

@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(); 
} 

Đây là dịch vụ được bắt đầu một cách chính xác, như hình dưới đây.

enter image description here

Làm thế nào tôi có thể bắt đầu và liên kết với một dịch vụ từ xa sử dụng Messenger để giao tiếp với các hoạt động từ một dự án Android thử nghiệm?

+0

Vui lòng thực hiện các kiểm tra này trước để đảm bảo vấn đề chính của nó không phải là một cái gì đó cú pháp đầu tiên Đảm bảo tệp kê khai của bạn có số này là '' và được lồng vào giữa thẻ ứng dụng như vậy ' ' Ngoài ra hãy đảm bảo rằng tất cả các phụ thuộc của dự án được ánh xạ chính xác Đồng thời kiểm tra xem coreservice.java của bạn có nằm trong cùng một gói hay không hoặc gói khác là hoạt động- đảm bảo bạn có tên gói ngay trong tệp kê khai. – Slartibartfast

+0

Như tôi đã nói: * "Điều này không xảy ra nếu tôi khởi chạy dịch vụ từ một Hoạt động" *, vì vậy rõ ràng là Manifest là chính xác. Cũng như bạn có thể thấy không có lỗi "Dịch vụ không tìm thấy", nhưng quá trình được khởi chạy nhưng không có dịch vụ nào được đính kèm? Đây là những gì tôi thấy lạ. – m0skit0

Trả lời

11

Toàn bộ điểm của Dự án thử nghiệm Android (test.apk) là để thiết kế Dự án ứng dụng (app.apk) và thử nghiệm đơn vị các thành phần Android (Hoạt động, Dịch vụ và v.v.) được liên kết với Dự án ứng dụng từ, kiểm tra đơn vị Hoạt động và Dịch vụ được tạo và thao tác bên trong app.apk.

Bạn không nên viết phần thực hiện MessengerService của mình một phần (Messenger, IncomingHandler và vv) lần thứ hai bên trong thực thi ServiceTestCase trong dự án thử nghiệm. Việc triển khai MessengerService chỉ cần được viết một lần trong tệp CoreService.java của dự án Ứng dụng của bạn.

ServiceConnection được sử dụng để liên lạc giữa Hoạt động và Dịch vụ, vì chúng tôi sử dụng ServiceTestCase tại đây (nghĩa là dịch vụ kiểm tra đơn vị, liên lạc với các thành phần khác không thuộc phạm vi), chúng tôi không cần ServiceConnection thực hiện. Điều duy nhất ServiceConnection không là khởi tạo một đối tượng messenger rắn để chúng ta có thể sử dụng sau này, một khi dịch vụ được tạo ra đúng cách:

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); 
} 

Cũng lưu ý rằng bạn không cần phải gọi ServiceTestCase.startService() trong trường hợp này, như ServiceTestCase.bindService() sẽ khởi động đúng dịch vụ (nếu nó chưa được bắt đầu) và trả về một đối tượng IBinder mà chúng ta cần sử dụng để khởi tạo đối tượng Messenger sau này.

Say nếu IncomingHandler.handleMessage() impelementation của bạn trong CoreService.java trông như thế này:

... ... 

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

... ... 

Để kiểm tra chức năng gửi tin nhắn trong 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 
    ... ... 
} 

... ... 

Nếu muốn bạn để kiểm tra thông tin liên lạc giữa Hoạt động và dịch vụ, sau đó ServiceTestCase không phù hợp trong trường hợp này. Hãy xem xét việc sử dụng ActivityInstrumentationTestCase2 kiểm tra Hoạt động thực tế (liên kết với Dịch vụ CoreService của bạn, cho phép bạn kiểm tra gián tiếp các chức năng Dịch vụ của mình.

+0

Vâng, đó là chính xác những gì tôi muốn làm: kiểm tra tin nhắn gửi đến dịch vụ, không phải là thông tin liên lạc dịch vụ ứng dụng <->. Cảm ơn bạn! – m0skit0

+0

@ m0skit0, vui mừng khi biết điều đó sẽ giúp :) – yorkw

7

Chỉ cần nhìn vào documentation for ServiceTestCase nó nói rằng test framework sự chậm trễ khởi động dịch vụ cho đến khi một trong những phương pháp thử nghiệm của bạn gọi ServiceTestCase.startService() hoặc ServiceTestCase.bindService().

Nhìn mã của bạn, bạn gọi ServiceTestCase.startService() trong phương pháp setUp(), không có trong phương pháp thử. Điều này chưa bắt đầu dịch vụ. Nó đang chờ một trong các phương pháp thử nghiệm của bạn để gọi ServiceTestCase.startService() hoặc ServiceTestCase.bindService().

Phương thức kiểm tra của bạn testBindService() không gọi số ServiceTestCase.bindService(), thay vào đó gọi số Context.bindService() và không thành công. Khung kiểm tra vẫn đang chờ đợi, vì vậy đó là lý do tại sao dịch vụ không được bắt đầu.

Có một cái nhìn khác về hỗ trợ Vòng đời trong tài liệu dành cho nhà phát triển được liên kết.

+0

Vấn đề là tôi không thể gọi 'ServiceTestCase.bindService()', điều đó vô dụng đối với tôi vì nó không có 'ServiceConnection'. – m0skit0

+1

Khung kiểm tra giao dịch với tất cả các công cụ kết nối. Nó quản lý ServiceConnection. Khi bạn gọi 'ServiceTestCase.bindService()', nó trả về một IBinder, đó là những gì bạn đã sử dụng ServiceConnection. Trong mọi trường hợp, nếu bạn không thể sử dụng khung kiểm tra này cho thử nghiệm của bạn bởi vì nó không cung cấp capabilites hoặc giao diện bạn cần, thì bạn sẽ chỉ cần viết khai thác thử nghiệm của riêng bạn mà không sử dụng khung này. –

Các vấn đề liên quan