2012-04-27 11 views
7

Tôi làm cách nào để tạo trường hợp thử nghiệm Android JUnit để kiểm tra nội dung của Mục đích được tạo trong một Hoạt động?Tôi làm cách nào để thử nghiệm một Intent được khởi chạy/gửi từ một Hoạt động?

Tôi có Hoạt động chứa cửa sổ EditText và khi người dùng đã nhập xong dữ liệu bắt buộc, Hoạt động sẽ khởi chạy Intent đến IntentService ghi dữ liệu và tiếp tục với quy trình đăng ký. Đây là lớp Tôi muốn thử nghiệm, các OnEditorActionListener/PasscodeEditorListener được tạo ra như là một lớp riêng biệt:

public class PasscodeActivity extends BaseActivity { 
    EditText     m_textEntry = null; 
    PasscodeEditorListener  m_passcodeEditorListener = null; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.passcode_activity); 

     m_passcodeEditorListener = new PasscodeEditorListener(); 
     m_textEntry = (EditText) findViewById(R.id.passcode_activity_edit_text); 
     m_textEntry.setTag(this); 
     m_textEntry.setOnEditorActionListener(m_passcodeEditorListener); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     /* 
     * If we're covered for any reason during the passcode entry, 
     * exit the activity AND the application... 
     */ 
     Intent finishApp = new Intent(this, CoreService.class); 
     finishApp.setAction(AppConstants.INTENT_ACTION_ACTIVITY_REQUESTS_SERVICE_STOP); 
     startService(finishApp); 
     finish(); 
    } 

} 



class PasscodeEditorListener implements OnEditorActionListener{ 
    @Override 
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 
     PasscodeActivity activity = (PasscodeActivity) v.getTag(); 
     boolean imeSaysGo = ((actionId & EditorInfo.IME_ACTION_DONE)!=0)?true:false; 
     boolean keycodeSaysGo = ((null != event) && 
       (KeyEvent.ACTION_DOWN == event.getAction()) && 
       (event.getKeyCode() == KeyEvent.KEYCODE_ENTER))?true:false; 

     if (imeSaysGo || keycodeSaysGo){ 
      CharSequence seq = v.getText(); 
      Intent guidEntry = new Intent(activity, CoreService.class); 
      guidEntry.setAction(AppConstants.INTENT_ACTION_PASSCODE_INPUT); 
      guidEntry.putExtra(AppConstants.EXTRA_KEY_GUID, seq.toString()); 
      activity.startService(guidEntry); 
      return true; 
     } 
     return false; 
    } 
} 

Làm thế nào tôi có thể đánh chặn hai Intents ngoài có thể được tạo ra bởi hoạt động và xác định nội dung của họ?

Cảm ơn

+0

Bạn đang sử dụng simulater? Có lẽ tôi đang thiếu một cái gì đó, nhưng bạn không thể chỉ kiểm tra nó theo cách đó? – Nick

+0

Tôi đã sử dụng cả trình mô phỏng và thiết bị cầm tay, mặc dù tôi không nghĩ có sự khác biệt. Tôi đã nhìn thấy một số cách để đưa Intents vào bất kỳ Activity cụ thể nào được kiểm tra, nhưng không phải là nhiều cách để xem đầu ra. Thấy một bài đăng khác là họ đã đặt ContextWrapper và chặn cuộc gọi đến "startService()". Điều này làm việc cho cuộc gọi đầu tiên, nhưng không phải là cuộc gọi tiếp theo. Một hoạt động có thể khởi chạy nhiều ý định mà không đóng, tôi quan tâm đến việc xem/thử nghiệm tất cả. –

Trả lời

6

Tôi đã tìm cách sử dụng ContextWrapper với sự trợ giúp của trang web khác.

Sử dụng ContextWrapper và ghi đè tất cả các chức năng dự định. Tổng quát cho tất cả các bài kiểm tra Hoạt động của tôi, tôi đã mở rộng lớp ActivityUnitTestCase và triển khai giải pháp dưới dạng một shim. Hãy tận hưởng:

import android.app.Activity; 
import android.app.Instrumentation; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.ContextWrapper; 
import android.content.Intent; 
import android.test.ActivityUnitTestCase; 

public class IntentCatchingActivityUnitTestCase<T extends Activity> extends ActivityUnitTestCase<T> { 

    protected Activity m_activity; 
    protected Instrumentation m_inst; 
    protected Intent[] m_caughtIntents; 
    protected IntentCatchingContext m_contextWrapper; 

    protected class IntentCatchingContext extends ContextWrapper { 
     public IntentCatchingContext(Context base) { 
      super(base); 
     } 

     @Override 
     public ComponentName startService(Intent service) { 
      m_caughtIntents = new Intent[] { service }; 
      return service.getComponent(); 
     } 

     @Override 
     public void startActivities(Intent[] intents) { 
      m_caughtIntents = intents; 
      super.startActivities(intents); 
     } 

     @Override 
     public void startActivity(Intent intent) { 
      m_caughtIntents = new Intent[] { intent }; 
      super.startActivity(intent); 
     } 

     @Override 
     public boolean stopService(Intent intent) { 
      m_caughtIntents = new Intent[] { intent }; 
      return super.stopService(intent); 
     } 
    } 

    // --// 
    public IntentCatchingActivityUnitTestCase(Class<T> activityClass) { 
     super(activityClass); 
    } 

    protected void setUp() throws Exception { 
     super.setUp(); 
     m_contextWrapper = new IntentCatchingContext(getInstrumentation().getTargetContext()); 
     setActivityContext(m_contextWrapper); 
     startActivity(new Intent(), null, null); 
     m_inst = getInstrumentation(); 
     m_activity = getActivity(); 
    } 

    protected void tearDown() throws Exception { 
     super.tearDown(); 
    } 

} 
+0

Thats một giải pháp tốt đẹp, tiếc là nó chỉ hoạt động với 'ActivityUnitTestCase', nhưng không phải với các trường hợp thử nghiệm chức năng. –

+0

Vâng, tôi đồng ý. Tôi cũng thấy rằng việc bắt vài Intent cũng không thể, ví dụ, Activity của tôi có thể gửi Intent trên một số điều kiện khởi động tới IntentService, sau đó khởi chạy một IntentService khác khi người dùng nhấn một nút. Không thể bắt tất cả. –

1

Ngoài ra, bạn có thể xác định lại mã của mình để làm bài kiểm tra đơn vị "sạch" (tôi có nghĩa là bài kiểm tra đơn vị có mọi thứ bị loại trừ bài kiểm tra). Trên thực tế, tôi có một tình huống bản thân mình, nơi tôi nhận được một java.lang.RuntimeException: Stub! bởi vì mã tôi muốn kiểm tra đơn vị tạo ra mới Intents chứa mocks mà tôi đã tiêm.

Tôi xem xét việc tạo nhà máy riêng cho mục đích. Sau đó, tôi có thể tiêm một nhà máy chế giễu ra để kiểm tra đẳng cấp dưới của tôi:

public class MyClassToBeTested { 
    public MyClassToBeTested(IntentFactory intentFactory) { 
     //assign intentFactory to field 
    } 
    .... 
    public void myMethodToTestUsingIntents() { 
     Intent i = intentFactory.create(); 
     i.setAction(AppConstants.INTENT_ACTION_PASSCODE_INPUT); 
     //when doing unit test, inject a mocked version of the 
     //IntentFactory and do the necessary verification afterwards. 
     .... 
    } 
} 

tình hình của tôi là không giống như bạn, nhưng tôi tin rằng bạn có thể áp dụng một nhà máy-pattern để giải quyết nó là tốt. Tôi thích viết mã để hỗ trợ các bài kiểm tra đơn vị thực sự, nhưng phải thừa nhận rằng giải pháp của bạn khá thông minh.