問題描述
我有一個嚴重依賴注入的 (dagger2) 應用程序.我想運行 espresso 測試,而無需讓測試瀏覽整個應用程序,然后登錄到應用程序.
I have a heavily dependency injected (dagger2) application. I would like to run an espresso test without having the test navigate through the whole application, and log into the application.
我想開始我的遠程活動,并模擬登錄管理器.然而,在任何@test 函數中,我們已經在調用onCreate 時命中了空指針.如果我在啟動活動(如下所示)之前覆蓋它,則活動為空.
I would like to start on my teleActivity, and mock the login manager. However in any @test function, we have already hit the null pointer as we have called onCreate. If I override it before we launch the activity (show below) the activity is null.
據我了解,切換下劃線依賴項的能力是我們使用 Dagger2 的一個重要原因,否則它將只是一個過度設計的單例.如何覆蓋、模擬或切換到測試匕首模塊的注入 - 這樣我就可以創建這個簡單的 espresso 測試.
To my understanding, the ability to switch our underlining dependencies is a large reason why we use Dagger2, else it would be just a very over engineered singleton. How do I override, mock, or switch the injection to a testing dagger module -- so I can create this simple espresso test.
請注意,如果有影響的話,我也在 MVP 設計模式中編寫了所有這些內容.
Note I also wrote all this in the MVP design pattern if that makes a difference.
遠程活動
@Inject
TelePresenter mTelePresenter;
@Inject
public LoginStateManager mLoginStateManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
DaggerInjectorTele.get().inject(this);
mTelePresenter.setTeleDependencies(this);
Intent intent = getIntent();
String searchId = null;
if (intent != null) {
searchId = intent.getStringExtra(Constants.SEARCH_ID);
}
mTelePresenter.onCreateEvent(searchId,
Helper.makeAuthorizationHeader(
// CRASH Null pointer
mLoginStateManager.getBaseLoginResponse().getAccessToken()));
}
濃縮咖啡
@LargeTest
@RunWith(AndroidJUnit4.class)
public class TeleTest {
@Rule
public ActivityTestRule<TeleActivity> mActivityTestRule = new ActivityTestRule(
TeleActivity.class) {
@Override
protected void beforeActivityLaunched() {
super.beforeActivityLaunched();
TeleActivity teleActivity = (TeleActivity)getActivity();
//teleActivity NULL!
teleActivity.mLoginStateManager = mock(LoginStateManager.class);
LoginResponse loginResponse = mock(LoginResponse.class);
when(loginResponse.getAccessToken()).thenReturn("1234");
// Nope here still null
when(teleActivity.mLoginStateManager.getBaseLoginResponse()).thenReturn(loginResponse);
}
};
匕首注射器
public class DaggerInjectorTele {
private static TelePresenterComponent telePresenterComponent =
DaggerTelePresenterComponent.builder().build();
public static TelePresenterComponent get() {
return telePresenterComponent;
}
}
TelePresenter組件
TelePresenterComponent
@Singleton
@Component(modules = {TelePresenterModule.class,
LoginStateManagerModule.class})
public interface TelePresenterComponent {
void inject(TeleActivity activity);
}
TelePresenter 模塊
TelePresenterModule
@Module
public class TelePresenterModule {
@Provides
@Singleton
public TelePresenter getTelePresenter() {
return new TelePresenter();
}
}
LoginStateManager 模塊
LoginStateManagerModule
@Module
public class LoginStateManagerModule {
@Provides
@Singleton
public LoginStateManager getLoginStateManager(){
return new LoginStateManager();
}
}
推薦答案
首先,您決定使用依賴注入 (Dagger2) 是一個非常好的決定,并且確實會讓您的測試更容易編寫.
First, your decision to use dependency injection (Dagger2) is a very good one and will indeed make your tests easier to write.
您必須覆蓋依賴注入配置(模塊)并注入一個模擬.下面是一個簡單的例子來說明如何做到這一點.
You have to override dependency injection configuration (module) and inject a mock. Here is a simple example of how it can be done.
首先你需要一個模擬:
LoginStateManager lsmMock = mock(LoginStateManager.class);
現在覆蓋 DI 配置以使用此模擬:
Now override the DI config to use this mock:
//Extend your TelePresenterModule, override provider method
public class TestTelePresenterModule extends TelePresenterModule{
@Override
public LoginStateManager getLoginStateManager() {
//simply return the mock here
return lsmMock;
}
}
現在開始測試:
@Test
//this is an espresso test
public void withAMock() {
//build a new Dagger2 component using the test override
TelePresenterComponent componentWithOverride = DaggerTelePresenterComponent.builder()
//mind the Test in the class name, see a class above
.telePresenterModule(new TestTelePresenterModule())
.build();
//now we initialize the dependency injector with this new config
DaggerInjectorTele.set(componentWithOverride);
mActivityRule.launchActivity(null);
//verify that injected mock was interacted with
verify(lsmMock).whatever();
}
示例來自:https://github.com/yuriykulikov/DIComparison/blob/master/app/src/androidTest/java/com/example/yuriy/dependencyinjectioncomparison/Dagger2Test.java
這篇關于Android 為 Espresso 測試模擬 Dagger2 注入依賴項的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!