首页 > 解决方案 > 在 Spring Boot 中的 mockito 测试中的 if...else 语句问题

问题描述

如何为 if...else 语句编写一个模拟测试用例,其中还包括异常测试,我对此感到很困惑。UserService 是一个接口

用户工厂.java

public class UserFactory {
    @Autowired
    private List<UserService> UserList;

    private final Map<String, UserService> UserMap = new HashMap<>();

    @PostConstruct
    public void initUserMap() {
        for (final UserService user : UserList) {
            UserMap.put(user.getUserId(), user);
        }
    }

    public UserService getUser(String userId) {
        final UserService userService = UserMap.get(userlId);
        if (null == userService) {
            throw new IllegalArgumentException("user are not in the group");
        }
        return userService;
    }
}

用户服务(接口)

public interface UserService{
  String getUserName();
  String getUserId();
}

这是我的测试,但它不正确......

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserService userService;

    @InjectMocks
    private UserFactory UserFactory;

    private Map<String, User> UserMap;

    private String userId = "123";

    @Before
    public void set_up(){
        UserMap = new HashMap<>();
        UserMap.put(userId, userService);
    }

    @Test
    public void getUser(){
        when(UserMap.get(userId)).thenReturn(userService);
        userService actual = userServiceFactory.getUser(userId);
        assertEquals(UserMap.get(userId), actual);
    }
}

标签: javaunit-testingspring-bootmockitospring-boot-test

解决方案


1)您编写单元测试,而不是切片测试或集成测试。所以这里 Spring Boot 无关紧要,因为您不需要加载容器来测试组件的逻辑。如果您有兴趣,
可以阅读我关于该领域的问题/答案。

2)逻辑中的分支(if/else)意味着您有多个场景。
不同的场景通常意味着不同的测试方法和有意义的名称。
您还可以依赖给定/何时/那么成语。

3)由于在您的测试中,分支的输入信息由模拟提供,这也意味着您将在每个测试方法中为模拟注册不同的行为。

4)UserService不需要被嘲笑。它必须是模拟返回的值,而不是模拟本身。在这里你必须模拟Map.

5)你测试UserFactory,所以你必须命名它UserFactoryTest

例如 :

@RunWith(MockitoJUnitRunner.class)
public class UserFactoryTest {

    @Mock
    private Map<String, User> UserMap;

    @InjectMocks
    private UserFactory UserFactory;

    private String userId = "123";


    @Test
    public void getUser(){
       when(UserMap.get(userId)).thenReturn(userService);
       userService actual = userServiceFactory.getUser(userId);
       assertEquals(UserMap.get(userId), actual);
    }


    @Test
    public void getUser_with_unknown_userId(){
        Assertions.assertThrows(IllegalArgumentException.class, 
                            ()->  userServiceFactory.getUser(userId));
    }

}

您注意到在第二种情况下,我没有为模拟注册任何行为。
默认情况下,Mockito 将返回null,实际上这是我引发异常所需要的。所以没关系。
另请注意,我通过依赖 JUnit 5 库而不是您似乎根据使用的跑步者使用的 JUnit 4 库来编写断言。
您应该考虑切换到 JUnit 5 进行新测试。


推荐阅读