提问者:小点点

使用Dagger模拟注入构造函数测试Android


嗨,我有一个问题。我想用espresso为Ui编写android测试,为了让测试不是乱七八糟的,我想嘲弄一下我的演示者。

我在应用程序里用匕首。我的配置如下:

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
   //some injections
   //some providings
}

我有组件的模块

@Module
public class AppModule {
   //providings for component
}

那么我也有一个用于活动的组件和一个用于组件的模块

@PerActivity
@Component(dependencies = AppComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
    //inject activites
    //provide subcomponents for activites
}

那么我的页面就有了子组件

@PerActivity
@Subcomponent(modules = InfoModule.class)
public interface InfoComponent {
    void inject(DetailActivity activity);
}

和子组件的模块

@Module
public class InfoModule {

    @Provides
    public DetailPresenter provideDetailPresenter(ShowDetailsUseCase showDetailsUseCase,
                                       OtherUseCase getPoisUseCase,
                                       AccountManager accountManager, Navigator
                                               navigator) {
        return new DetailPresenter(showDetailsUseCase, otherUseCase, accountManager, navigator);
    }
}

然后详细信息activity注入DetailPresenter

public class DetailActivity extends BaseActivity {

    @Inject
    DetailPresenter mPresenter;

    InfoComponent mComponent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mComponent = getActivityComponent().provideInfoModule(new InfoModule());
        mComponent.inject(this);
        mPresenter.bindView(this);
        mPresenter.onCreate(new PresenterBundle(getIntent().getExtras(), savedInstanceState));
    }
    //functionality of detailActiviy
}

然后是使用构造函数注入的presenter

public class DetailPresenter extends BasePresenter {


    private ShowDetailsUseCase mDetailsUseCase;
    private final OtherUseCase getPoisUseCase;

    private AccountManager accountManager;
    private Navigator navigator;

    @Inject
    public DetailPresenter(ShowDetailsUseCase getDetailsUseCase, OtherUseCase getPoisUseCase,
    AccountManager
    accountManager, Navigator navigator) {
        this.mDetailsUseCase = getDetailsUseCase;
        this.getPoisUseCase = gotherUseCase;
        this.accountManager = accountManager;
        this.navigator = navigator;
    }

    @Override
    public void onCreate(@Nullable PresenterBundle bundle) {
        super.onCreate(bundle);
        //other things to do on initialization
        ((DetailView) getView()).showDetails(getDetailsFromUseCase());

    }
}

现在在测试中,我要做的是模拟演示者:

@RunWith(AndroidJUnit4.class)
public class DetailActivityTest {

    @Rule
    public final ActivityTestRule<DetailActivity> main = new ActivityTestRule<DetailActivity>(DetailActivity.class, true, false);

    @Rule
    public final DaggerMockRule<AppComponent> rule=new EspressoDaggerMockRule();

    @Mock
    DetailPresenter presenter; //does not work because @Inject constructor


    @Test
    public void locationTest() {

        Details details = generateDetails();

        launchActivity();

        doAnswer(answer -> {
                    activity.showDetails(details);
                    return null;
                }

        ).when(presenter).onCreate(any());

        //espresso verify afterwards
    }
}

但如果我尝试模拟,则会出现以下错误:

java.lang.RuntimeException: Error while trying to override objects:
a.b.c.ui.mvp.presenter.DetailPresenter
You must define overridden objects using a @Provides annotated method instead of using @Inject annotation

有没有人知道,我如何能够模仿演示者,即使使用@inject构造函数和依赖项。我不想模拟数据层,因为这样我就必须模拟database、apiClient、cacheData等等。一些数据层也有注入依赖项,所以我也不能模仿它们。

事先谢谢你


共1个答案

匿名用户

DetailPresenter类是在InfoModule中创建的,因此您不需要Inject批注。您得到的错误是因为使用DaggerMock,您只能替换在模块中创建的对象。在您的示例中,您已经在一个模块中创建了它,您只需要删除inject注释。