You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Espresso Dagger测试:构造注入下Mock Presenter的实现

如何Mock通过构造注入的Presenter并注入到Activity中?

你的场景我完全理解:RegistrationActivity通过构造注入拿到RegistrationPresenter,但Mock这个Presenter时,发现只有把Presenter放到Module里提供才能生效。这其实是因为Dagger的注入优先级——当有Module提供实例时会优先使用Module的逻辑,而构造注入的类在测试时需要我们通过测试组件或直接替换的方式,覆盖默认的注入逻辑。下面给你两种实用的解决方案:

方案一:构建测试专用的Dagger组件与Module

这种方式贴合Dagger原生逻辑,适合需要完整注入环境的测试场景:

  1. 创建Mock Presenter
    你可以自定义Mock类继承原Presenter,也可以直接用Mockito生成Mock实例:

    // 方式1:自定义Mock类
    public class MockRegistrationPresenter extends RegistrationPresenter {
        @Inject
        public MockRegistrationPresenter() {
            super();
        }
    
        // 重写方法,返回测试需要的预设行为
        @Override
        public void handleRegistration() {
            // 测试专属逻辑
        }
    }
    
    // 方式2:用Mockito生成Mock(更灵活)
    // RegistrationPresenter mockPresenter = Mockito.mock(RegistrationPresenter.class);
    
  2. 编写测试Module
    这个Module的核心作用是把Presenter的绑定替换成Mock版本:

    @Module
    public class TestRegistrationModule {
        @Provides
        RegistrationPresenter provideRegistrationPresenter() {
            // 返回自定义Mock类或者Mockito生成的Mock实例
            return new MockRegistrationPresenter();
            // 或者 return Mockito.mock(RegistrationPresenter.class);
        }
    }
    
  3. 创建测试组件
    让测试组件继承原Application组件的接口,替换掉对应的Module:

    @Component(modules = {TestRegistrationModule.class, /* 原Application组件依赖的其他Module */})
    public interface TestRegistrationComponent extends ApplicationComponent {
        void inject(RegistrationActivity activity);
    }
    
  4. 在测试中替换Application组件
    测试前把App里的原组件换成测试组件,这样Activity启动时就会自动注入Mock的Presenter:

    @RunWith(AndroidJUnit4.class)
    public class RegistrationActivityTest {
        @Rule
        public ActivityScenarioRule<RegistrationActivity> activityRule = 
            new ActivityScenarioRule<>(RegistrationActivity.class);
    
        @Before
        public void setup() {
            SampleApplication app = (SampleApplication) InstrumentationRegistry.getInstrumentation()
                .getTargetContext().getApplicationContext();
            // 构建测试组件
            TestRegistrationComponent testComponent = DaggerTestRegistrationComponent.create();
            // 需要在SampleApplication中添加setApplicationComponent方法,用来替换组件
            app.setApplicationComponent(testComponent);
        }
    
        // 你的测试用例
        @Test
        public void testRegistrationFlow() {
            // 执行测试逻辑,验证Mock Presenter的行为是否符合预期
        }
    }
    

方案二:直接替换Activity中的Presenter字段(快速简单)

如果你的测试不需要完整的Dagger注入环境,直接给Activity里的Presenter字段赋值是最快捷的方式:

@RunWith(AndroidJUnit4.class)
public class RegistrationActivityTest {
    @Mock
    RegistrationPresenter mockPresenter;

    @Before
    public void setup() {
        MockitoAnnotations.openMocks(this);
        
        // 启动Activity场景,替换Presenter字段
        ActivityScenario<RegistrationActivity> scenario = ActivityScenario.launch(RegistrationActivity.class);
        scenario.onActivity(activity -> {
            // 如果字段是private的,可以用反射设置,或者把字段改成包访问权限
            activity.registrationPresenter = mockPresenter;
        });
    }

    @Test
    public void testRegisterButtonClick() {
        // 模拟点击注册按钮
        // 验证Mock Presenter的方法是否被调用
        Mockito.verify(mockPresenter).register(anyString(), anyString());
    }
}

注意:如果原Presenter字段是private的,要么改成包访问权限(测试目录下可直接访问),要么用反射工具类(比如Mockito的Whitebox)来设置值。

额外优化建议:面向接口编程

最好让RegistrationPresenter实现一个接口(比如RegistrationContract.Presenter),然后Activity中注入的是这个接口而非具体类。这样Mock时只需要Mock接口,不需要依赖具体实现,Dagger绑定也会更灵活:

// 定义接口
public interface RegistrationContract {
    interface Presenter {
        void register(String username, String password);
    }
}

// 原Presenter实现接口
public class RegistrationPresenter implements RegistrationContract.Presenter {
    @Inject
    public RegistrationPresenter() {}

    @Override
    public void register(String username, String password) {
        // 业务逻辑
    }
}

原Module中绑定接口到实现类,测试时只需要把接口的绑定换成Mock接口即可,扩展性更强。

内容的提问来源于stack exchange,提问作者Булат Мухутдинов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:25:02