由於方法getApplicationContext
位於您正在擴展的類中,因此會變得有些問題。有幾個問題需要考慮:
你可以在這種情況下做的,是喜歡object composition over inheritance。所以爲了讓你的Activity
可測試,你需要將邏輯分解一點。假設你的Activity
被稱爲MyActivity
。它需要由組成的一個邏輯組件(或類),讓它命名爲MyActivityLogic
。下面是一個簡單的類圖圖:
爲了解決上述問題單,我們讓邏輯是與應用程序上下文中,「注入」,因此它可以用一個模擬測試。然後,我們只需測試MyActivity
對象是否已將正確的應用程序上下文放入MyActivityLogic
。我們如何基本解決這兩個問題是通過another layer of abstraction(從Butler Lampson轉述)。在這種情況下,我們添加的新層是在活動對象之外移動的活動邏輯。
對於示例的緣故類需要尋找排序的是這樣的:
public final class MyActivityLogic {
private MyApp mMyApp;
public MyActivityLogic(MyApp pMyApp) {
mMyApp = pMyApp;
}
public MyApp getMyApp() {
return mMyApp;
}
public void onClick(View pView) {
getMyApp().setNewState();
}
}
public final class MyActivity extends Activity {
// The activity logic is in mLogic
private final MyActivityLogic mLogic;
// Logic is created in constructor
public MyActivity() {
super();
mLogic = new MyActivityLogic(
(MyApp) getApplicationContext());
}
// Getter, you could make a setter as well, but I leave
// that as an exercise for you
public MyActivityLogic getMyActivityLogic() {
return mLogic;
}
// The method to be tested
public void onClick(View pView) {
mLogic.onClick(pView);
}
// Surely you have other code here...
}
它都應該是這個樣子:
要測試MyActivityLogic
你只需要一個簡單的JUnit TestCase
代替ActivityUnitTestCase
(因爲它不是一個Activity),您可以使用您選擇的模擬框架嘲笑你的應用環境(因爲手卷自己的嘲弄有點拖累)。示例使用Mockito:
MyActivityLogic mLogic; // The CUT, Component Under Test
MyApplication mMyApplication; // Will be mocked
protected void setUp() {
// Create the mock using mockito.
mMyApplication = mock(MyApplication.class);
// "Inject" the mock into the CUT
mLogic = new MyActivityLogic(mMyApplication);
}
public void testOnClickShouldSetNewStateOnAppContext() {
// Test composed of the three A's
// ARRANGE: Most stuff is already done in setUp
// ACT: Do the test by calling the logic
mLogic.onClick(null);
// ASSERT: Make sure the application.setNewState is called
verify(mMyApplication).setNewState();
}
要測試MyActivity
您使用ActivityUnitTestCase
像往常一樣,我們只需要確保它創建一個具有正確ApplicationContext
一個MyActivityLogic
。粗略的測試代碼示例,可以完成所有這些工作:
// ARRANGE:
MyActivity vMyActivity = getActivity();
MyApp expectedAppContext = vMyActivity.getApplicationContext();
// ACT:
// No need to "act" much since MyActivityLogic object is created in the
// constructor of the activity
MyActivityLogic vLogic = vMyActivity.getMyActivityLogic();
// ASSERT: Make sure the same ApplicationContext singleton is inside
// the MyActivityLogic object
MyApp actualAppContext = vLogic.getMyApp();
assertSame(expectedAppContext, actualAppContext);
希望這一切對您有意義並幫助您。
我與_getApplication()代替_getApplicationContext()_的理念上來。現在,我可以嘲笑_Application_對象,並使用_setApplication()_。這是有點解決方法。但是,我沒有得到這些方法之間的區別。而[問題](http://stackoverflow.com/questions/5018545)與未回答。 – lstipakov 2011-04-16 12:22:06