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

如何使用Mockito测试setDeviceColor方法?我无法完成该测试

用Mockito实现setDeviceColor的参数化测试

没问题,我来一步步教你覆盖这个方法的所有测试场景。先拆解下这个方法的核心逻辑:

  • 当传入的deviceColor为0时,会调用ColorUtil.getColorFromConte()获取颜色值,再赋值给mDeviceColor
  • 当传入非0值时,直接将传入值赋值给mDeviceColor
  • 两种场景下最终都会调用notifyPropertyChanged(BR.deviceColor)

接下来结合Mockito和JUnit参数化测试来完成测试:

1. 先准备测试依赖

如果用Maven,确保pom.xml包含这些依赖(Gradle可对应调整):

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>4.11.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>4.11.0</version>
    <scope>test</scope>
</dependency>

2. 测试类完整实现

假设这个方法属于DeviceViewModel类,测试代码如下:

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
public class DeviceViewModelTest {

    @Mock
    private Context mContext; // Mock上下文对象

    // 用CsvSource批量提供测试用例:输入颜色值、预期最终颜色、是否需要调用ColorUtil
    @ParameterizedTest
    @CsvSource({
        "0, 0xFF123456, true", // 假设ColorUtil返回0xFF123456
        "123, 123, false",
        "-1, -1, false"
    })
    void testSetDeviceColor(int inputColor, int expectedColor, boolean shouldCallColorUtil) {
        // 1. 实例化被测对象,注入mock的上下文
        DeviceViewModel viewModel = new DeviceViewModel(mContext);

        // 2. Mock静态方法ColorUtil(Mockito 3.4+支持静态类Mock)
        try (MockedStatic<ColorUtil> mockedColorUtil = mockStatic(ColorUtil.class)) {
            if (shouldCallColorUtil) {
                // 指定静态方法的返回值
                mockedColorUtil.when(() -> ColorUtil.getColorFromConte(mContext, R.color.color_1))
                               .thenReturn(expectedColor);
            }

            // 3. 调用被测方法
            viewModel.setDeviceColor(inputColor);

            // 4. 验证逻辑正确性
            if (shouldCallColorUtil) {
                // 验证静态方法被调用一次
                mockedColorUtil.verify(() -> ColorUtil.getColorFromConte(mContext, R.color.color_1), times(1));
            } else {
                // 验证静态方法从未被调用
                mockedColorUtil.verify(() -> ColorUtil.getColorFromConte(any(Context.class), anyInt()), never());
            }

            // 验证mDeviceColor被设置为预期值(建议给ViewModel加getDeviceColor()方法,或用反射获取私有变量)
            assertEquals(expectedColor, viewModel.getDeviceColor());

            // 验证属性变更通知被触发
            verify(viewModel, times(1)).notifyPropertyChanged(BR.deviceColor);
        }
    }
}

关键细节说明

  • 参数化测试:用@CsvSource批量定义测试场景,一次运行就能覆盖0、正整数、负整数等多种情况
  • 静态方法Mock:用MockedStatic(try-with-resources语法)确保静态mock在测试后自动清理,避免影响其他测试
  • 验证逻辑:
    • 针对0值场景,确认静态方法被正确调用,返回值被赋值
    • 针对非0值场景,确认静态方法未被调用,输入值直接生效
    • 所有场景都验证notifyPropertyChanged的调用,确保属性变更通知正常

额外注意点

  • 如果用JUnit 4,参数化测试要改用@RunWith(Parameterized.class),静态Mock可能需要PowerMock(Mockito 3.4之前版本不支持静态mock)
  • 若mDeviceColor是私有变量,建议添加getDeviceColor()测试专用方法,或用反射工具类读取私有值
  • 确保测试环境能正常访问R.color.color_1,必要时可Mock资源ID的返回逻辑

内容的提问来源于stack exchange,提问作者rahul kumar abhishek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:24:36