当前位置: 首页 > 知识库问答 >
问题:

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

富念
2023-03-14

嗨,我有一个问题。我想用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个答案

公冶经纶
2023-03-14

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

 类似资料:
  • 好的,到目前为止还好。但是等等,突然A需要额外的输入,比如一个对它的构造至关重要的名为“amount”的整数。现在,我的A构造函数需要如下所示: 突然这个新参数干扰了注射。此外,即使这确实有效,我也无法在从提供者检索新实例时输入“金额”,除非我弄错了。这里有几件事我可以做,我的问题是哪一件是最好的? 我可以通过添加一个方法来重构A,该方法应该在构造函数之后调用。然而,这是很难看的,因为它迫使我推迟

  • 我刚开始学习Dagger2,以解决一个特定的问题:我试图遵循MVVM架构,我的应用程序有一个存储库类,它将设置提取并保存在一个基本上包装SharedPreferences的CacheData类中。但是,SharedPreferences具有上下文相关性。由于我已经完成了将存储库和数据层与视图和应用程序类解耦的所有工作,传递上下文似乎是一种倒退。 下面是存储库类 应用程序类: 是否可以使用Dagge

  • 问题内容: 我开始在正在开发的应用程序中使用Dagger 2,但是我对Dagger 2的工作方式有一些疑问。 我得到了@Provides方法和@Inject批注背后的所有逻辑来初始化您的依赖关系,但是类构造函数的@Inject批注使我感到烦恼。 例如: 在我的应用程序中,我定义了一个模块ContextModule来检索应用程序的上下文: ContextModule.java 我的BaseActiv

  • 我想将我的房间存储库和Rest存储库注入到我的ViewModel类中。然而,我可以注入rest存储库,但当我尝试注入room存储库时,它会出错。 错误是这样的: 错误:[dagger.android.AndroidInjector.inject(T)]me.ibrahimsn.capsules.data.local.message.如果没有@Provides-anttated方法,则无法提供Mes

  • 我试图使用构造函数注入依赖模式。 我想知道在集成测试类上注入JPA存储库的正确方法是什么: RepoClass 注射后的服务 测试它:(我的问题来了) SpringRunner类选项1:构造函数注入 由于控制台输出显示: 测试类应该只有一个公共零参数构造函数 SpringRunner级选项2:自动注射 我觉得它正在打破人们想要的模式。 SpringRunner类选项3:空构造函数 正如所评论的:显