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

时间:2016-09-21 09:16:25

标签: android mockito dagger-2 dagger android-espresso

您好我有以下问题。我想用Ui为esi编写android测试,并且为了进行非片状的测试,我想模仿我的演示者。

我在App中使用Dagger。我的配置如下:

/**
 * returns default value if column is not present in resultset
 * 
 * @param rs
 * @param columnLabel
 * @param defaultValue
 * @return
 */
@SuppressWarnings("unchecked")
private static <T> T getValueFromResultSet(final ResultSet rs,
        String columnLabel, T defaultValue) {
    try {
        return (T) rs.getObject(columnLabel);
    } catch (SQLException e) {
        return defaultValue;
    }
}

我有一个组件模块

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

然后详细活动注入DetailPresenter

@Module
public class InfoModule {

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

然后我有使用构造函数注入的演示者

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
}

现在在测试中我想模仿演示者:

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

有人知道我是如何使用@Inject构造函数和依赖项来模拟演示者的。 我不想模拟数据层,因为那时我必须模拟数据库,apiClient,cacheData等。而且一些数据层也有注入依赖项,所以我也不能嘲笑它们。

提前谢谢

1 个答案:

答案 0 :(得分:1)

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