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

Android应用Java单元测试:验证方法调用求助

解决Android Java单元测试中方法调用验证的问题

嘿,我来帮你搞定这个单元测试的问题!你要验证beeperChanged方法里是否正确调用了b.setBeeper(active)和savePrinterToData(b),用Mockito框架就能轻松实现,这是Android单元测试里验证方法调用的常用方案。

先明确测试目标

我们要验证两个核心行为:

  • 当调用beeperChanged(boolean)时,类B的实例b的setBeeper方法被传入正确的active参数调用
  • savePrinterToData方法被传入这个b实例调用

准备工作:添加Mockito依赖

如果你的项目用Gradle构建,在build.gradle(Module级)的dependencies里添加测试依赖:

testImplementation 'org.mockito:mockito-core:4.11.0'
testImplementation 'junit:junit:4.13.2'

分场景给出测试代码

下面分两种常见场景来写测试用例:

场景1:savePrinterToData是类A的方法

假设你的类结构是这样的:

public class A {
    private B b;

    // 构造函数注入B实例
    public A(B b) {
        this.b = b;
    }

    @Override
    public void beeperChanged(boolean active) {
        b.setBeeper(active);
        savePrinterToData(b);
    }

    // 假设这是A类的方法(可能是protected或public)
    protected void savePrinterToData(B printer) {
        // 实际保存逻辑
    }
}

public class B {
    public void setBeeper(boolean active) {
        // 实际逻辑
    }
}

对应的测试类:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.verify;

@RunWith(MockitoJUnitRunner.class)
public class ATest {

    @Mock
    private B mockB; // 创建B的Mock对象,用来验证setBeeper的调用

    @Spy
    private A spyA; // 创建A的Spy对象,既能执行真实逻辑,又能验证内部方法调用

    // 初始化测试对象
    public ATest() {
        spyA = new A(mockB);
    }

    @Test
    public void beeperChanged_ShouldCallSetBeeperAndSavePrinterToData() {
        boolean testActive = true;

        // 调用待测试的方法
        spyA.beeperChanged(testActive);

        // 验证B的setBeeper方法被传入testActive调用了一次(times(1)是默认值,可省略)
        verify(mockB).setBeeper(testActive);

        // 验证savePrinterToData方法被传入mockB实例调用了一次
        verify(spyA).savePrinterToData(mockB);
    }
}

场景2:savePrinterToData是其他类的方法(比如DataManager)

如果savePrinterToData是另一个类的方法,比如负责数据存储的DataManager,类结构如下:

public class A {
    private B b;
    private DataManager dataManager;

    // 构造函数注入依赖
    public A(B b, DataManager dataManager) {
        this.b = b;
        this.dataManager = dataManager;
    }

    @Override
    public void beeperChanged(boolean active) {
        b.setBeeper(active);
        dataManager.savePrinterToData(b);
    }
}

public class DataManager {
    public void savePrinterToData(B printer) {
        // 保存到本地或远程的逻辑
    }
}

对应的测试类:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.verify;

@RunWith(MockitoJUnitRunner.class)
public class ATest {

    @Mock
    private B mockB;

    @Mock
    private DataManager mockDataManager; // Mock数据管理类

    private A a;

    @Before
    public void setup() {
        // 初始化A实例,注入Mock的依赖
        a = new A(mockB, mockDataManager);
    }

    @Test
    public void beeperChanged_ShouldCallSetBeeperAndSavePrinterToData() {
        boolean testActive = true;

        a.beeperChanged(testActive);

        // 验证B的setBeeper调用
        verify(mockB).setBeeper(testActive);

        // 验证DataManager的savePrinterToData调用
        verify(mockDataManager).savePrinterToData(mockB);
    }
}

关键知识点说明

  • Mock vs Spy:Mock是完全模拟的对象,不会执行真实方法;Spy是真实对象的包装,会执行真实方法,同时允许验证方法调用。如果只需要验证方法调用,用Mock即可;如果需要执行真实逻辑同时验证内部调用,用Spy。
  • verify方法:用来确认方法是否被调用,以及调用时的参数是否正确。默认验证调用次数为1次,你也可以用verify(mockB, times(2))来验证调用2次,或者never()验证从未调用。
  • 不要直接验证私有方法:如果savePrinterToData是私有方法,不建议直接验证,因为单元测试应该关注公开方法的行为,而不是内部实现细节。如果一定要验证,可以用PowerMock,但更推荐通过公开方法的输出结果来间接验证。

内容的提问来源于stack exchange,提问作者Jonses

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:18:17