如何用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()类型参数,导致代码报错。
解决步骤与正确测试代码
问题根源
- Mockito默认不支持直接通过
when()语法mock静态方法,需要使用mockStaticAPI(Mockito 3.4+版本支持)。 - 原始代码的
when语法错误,静态方法的mock方式不符合Mockito规范。 - 未静态导入Mockito的匹配器(如
anyString()),导致类型不兼容。 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
相关产品推荐
相关产品推荐

