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

如何用JUnit和Mockito单元测试Android Log包装类方法

用JUnit和Mockito测试Logger包装类的问题解决

问题场景

需要仅通过JUnit和Mockito测试自定义的Logger包装类,现有测试代码在setup方法中遇到when()方法不接受anyString()类型的错误。

Logger包装类代码

import android.util.Log;

public class Logger{
    public static void v(String tag,String logMessage){
        Log.v(tag,logMessage);
    }
    public static void v(String tag,String logMessage,Throwable throwable){
        Log.v(tag,logMessage);
    }
}

原始测试代码(存在问题)

import android.util.Log;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ModelTest {

    @Before
    public void setup(){
        when(Logger.v(anyString(),anyString())).thenCallRealMethod(Log.v(anyString(),anyString()));
        when(Logger.v(anyString(),anyString()),any(Throwable.class)).thenCallRealMethod(Log.v(anyString(),anyString()));
    }

    @Test
    public void v(){
        Logger.v("Tag.v"," Message from Tag.v");
        Logger.v("Tag.v throw"," Message from Tag.v throw");
    }
}

遇到的问题

setup方法中,when()方法无法接受anyString()类型参数,导致代码报错。


解决步骤与正确测试代码

问题根源

  1. Mockito默认不支持直接通过when()语法mock静态方法,需要使用mockStaticAPI(Mockito 3.4+版本支持)。
  2. 原始代码的when语法错误,静态方法的mock方式不符合Mockito规范。
  3. 未静态导入Mockito的匹配器(如anyString()),导致类型不兼容。
  4. thenCallRealMethod的用法错误,不需要传递方法调用作为参数。

正确测试实现

我们的核心测试目标是验证Logger是否正确将调用转发给android.util.Log的对应静态方法,因此应该mockLog类而非Logger本身:

import android.util.Log;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.junit.MockitoJUnitRunner;

// 静态导入Mockito核心方法和匹配器
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class LoggerTest {

    @Test
    public void testV_withTagAndMessage() {
        // 使用try-with-resources自动管理静态mock的生命周期
        try (MockedStatic<Log> mockedLog = mockStatic(Log.class)) {
            // 执行Logger的测试方法
            Logger.v("TestTag", "TestLogMessage");
            
            // 验证Log.v是否被正确调用,参数匹配
            mockedLog.verify(() -> Log.v("TestTag", "TestLogMessage"));
        }
    }

    @Test
    public void testV_withTagMessageAndThrowable() {
        Throwable testException = new RuntimeException("Test error");
        
        try (MockedStatic<Log> mockedLog = mockStatic(Log.class)) {
            Logger.v("TestTag", "Error Log", testException);
            
            // 注意:原Logger的重载方法中仅调用了Log.v(tag, logMessage),未传递Throwable参数
            // 如果后续修改Logger实现传递Throwable,这里要改成对应的验证逻辑
            mockedLog.verify(() -> Log.v("TestTag", "Error Log"));
        }
    }
}

关键说明

  • 使用mockStatic(Log.class)创建静态类的mock,通过try-with-resources确保mock在测试结束后自动销毁,避免影响其他测试用例。
  • 通过verify方法验证Log类的静态方法是否被Logger正确调用,参数完全匹配。
  • 无需复杂的@Before配置,每个测试方法独立管理mock逻辑,更符合单元测试的隔离性要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:15:34