如何用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
相关产品推荐
相关产品推荐

