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

如何用JUnit 4+Mockito编写测试覆盖if语句的两个分支?

如何用JUnit 4 + Mockito测试if条件分支

问题背景

我是JUnit新手,正在使用JUnit 4搭配Mockito,需要为Java代码中的if条件编写测试,覆盖question != null进入分支和question == null的分支。相关代码如下:

public class MyClass{
    private HttpServletRequest request;
    private A a;    
    private B b;

    public void go(String something, String s){
        MyQuestion question = Exam.getSubject().getMarks(a.getAId(), b.getBId(), something);
      
        if(question != null){
            request.setAttribute(s, question);
        }
    }
}

另外getMarks方法包含异常捕获逻辑:

public class MarksClass{
    public MyQuestion getMarks(long idA, long idB, String s){        
        try{
            // 业务逻辑
        }catch(Exception e){
            throw new SomeException("exception" + e);
        }
    }
}

解决方案

1. 依赖与测试类基础配置

确保项目引入mockito-inline依赖(Mockito 3.4+版本支持,用于mock静态方法),测试类基础配置如下:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
    @Mock
    private HttpServletRequest request; // Mock请求对象
    @Mock
    private A a; // Mock类A实例
    @Mock
    private B b; // Mock类B实例
    @InjectMocks
    private MyClass myClass; // 将Mock对象注入到被测类实例

    // 测试方法编写区域
}

2. 测试question != null分支

模拟getMarks返回非null的MyQuestion,验证request.setAttribute被正确调用:

@Test
public void go_whenQuestionIsNotNull_shouldCallSetAttribute() {
    // 1. 模拟a、b的ID返回值
    when(a.getAId()).thenReturn(1L);
    when(b.getBId()).thenReturn(2L);

    // 2. Mock静态方法Exam.getSubject(),返回Mock的MarksClass实例
    try (MockedStatic<Exam> mockedExam = mockStatic(Exam.class)) {
        MarksClass mockMarksClass = mock(MarksClass.class);
        mockedExam.when(Exam::getSubject).thenReturn(mockMarksClass);

        // 3. 模拟getMarks返回非null的MyQuestion
        MyQuestion mockQuestion = mock(MyQuestion.class);
        when(mockMarksClass.getMarks(1L, 2L, "test-something")).thenReturn(mockQuestion);

        // 4. 调用被测方法
        myClass.go("test-something", "test-attribute-key");

        // 5. 验证request.setAttribute被调用一次,参数匹配
        verify(request, times(1)).setAttribute("test-attribute-key", mockQuestion);
    }
}

3. 测试question == null分支

模拟getMarks返回null,验证request.setAttribute不会被调用:

@Test
public void go_whenQuestionIsNull_shouldNotCallSetAttribute() {
    // 1. 模拟a、b的ID返回值
    when(a.getAId()).thenReturn(1L);
    when(b.getBId()).thenReturn(2L);

    // 2. Mock静态方法和MarksClass实例
    try (MockedStatic<Exam> mockedExam = mockStatic(Exam.class)) {
        MarksClass mockMarksClass = mock(MarksClass.class);
        mockedExam.when(Exam::getSubject).thenReturn(mockMarksClass);

        // 3. 模拟getMarks返回null
        when(mockMarksClass.getMarks(1L, 2L, "test-something")).thenReturn(null);

        // 4. 调用被测方法
        myClass.go("test-something", "test-attribute-key");

        // 5. 验证request.setAttribute从未被调用
        verify(request, never()).setAttribute(anyString(), any());
    }
}

4. 可选:测试getMarks抛出异常的场景

如果需要覆盖getMarks抛出SomeException的分支,可添加以下测试:

@Test(expected = SomeException.class)
public void go_whenGetMarksThrowsException_shouldPropagateException() {
    when(a.getAId()).thenReturn(1L);
    when(b.getBId()).thenReturn(2L);

    try (MockedStatic<Exam> mockedExam = mockStatic(Exam.class)) {
        MarksClass mockMarksClass = mock(MarksClass.class);
        mockedExam.when(Exam::getSubject).thenReturn(mockMarksClass);

        // 模拟getMarks抛出指定异常
        when(mockMarksClass.getMarks(1L, 2L, "test-something"))
                .thenThrow(new SomeException("test exception"));

        // 调用被测方法,预期抛出SomeException
        myClass.go("test-something", "test-attribute-key");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:40:37