java JUnit Test中的Mock对象为null

z9ju0rcb  于 2023-05-21  发布在  Java
关注(0)|答案(2)|浏览(284)

我使用Mockito在JUnit中设计测试。问题出现在以下测试中:

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    
    @InjectMocks
    private UserService userService;
    @Mock
    private UserDAO userDAO;
    @Mock
    private ModelMapper modelMapper;
    @Mock
    private UserDTOMapper userDTOMapper;

    private User user;
    private UserDTO userDTO;

    private AutoCloseable closeable;

    @BeforeTestMethod
    public void initMocks(){
        MockitoAnnotations.openMocks(this);
    }

    @BeforeEach
    void setUp() {
        userDTO = UserDTO.builder()
                .username("johnny")
                .firstname("John")
                .surname("Rogers")
                .email("john@gmail.com")
                .phoneNumber("0123456789")
                .role(Role.ADMIN).build();
        user = User.builder()
                .username("johnny")
                .password("johnny123")
                .firstname("John")
                .surname("Rogers")
                .email("john@gmail.com")
                .phoneNumber("0123456789")
                .role(Role.ADMIN).build();
    }

    @Test
    void findUser() {
        userDao.sace(user);
        assertEquals(userDTO, userService.findUser(user.getUsername()));
    }

    @Test
    void convertToDto() {
        assertEquals(userDTO, userDTOMapper.apply(user));
    }

    @AfterTestMethod
    public void releaseMocks() throws Exception {
        closeable.close();
    }
}

测试针对此服务类:

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserDAO userDAO;
    private final ModelMapper modelMapper;
    private final UserDTOMapper userDTOMapper;

    public UserDTO findUser(String username) {
        User user = userDAO.findUserByUsername(username);
        return userDTOMapper.apply(user);
    }

    public UserDTO convertToDto(User user) {
        return modelMapper.map(user, UserDTO.class);
    }
}

错误:

org.opentest4j.AssertionFailedError: 
Expected :UserDTO(id=0, username=johnny, firstname=John, surname=Rogers, email=john@gmail.com, phoneNumber=0123456789, role=USER)
Actual   :null
<Click to see difference>

    at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
    at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
    at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
    at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1142)

我真的不知道是什么问题,还是我做错了什么?起初,我以为问题出在“@RequiredArgsConstructor”注解中,但这不是问题。我确信解决方案很简单,但我真的不明白为什么所有模拟的对象都是NULL

wf82jlnq

wf82jlnq1#

1.你不需要使用openMocks()。注解@ExtendWith(MockitoExtension.class)已经为您完成了。
1.您没有对依赖项的任何行为进行存根。
1.移除after和before方法。如果你想为你的User和Dto创建示例,只需要使用私有方法。不需要在每次测试后都创建它。
这是我的例子,它应该是什么样子。如果成功了,你就可以开始重构了:

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {

    @Mock
    private UserDAO userDAO;

    @Mock
    private ModelMapper modelMapper;

    @InjectMocks
    private UserService userService;

    @Test
    public void testFindUser() {
        // Arrange
        String username = "testUser";
        User user = User.builder()
                .id(1)
                .username(username)
                .firstname("John")
                .surname("Doe")
                .email("johndoe@example.com")
                .phoneNumber("123456789")
                .role(Role.USER)
                .build();
        when(userDAO.findUserByUsername(username)).thenReturn(user);

        UserDTO expectedDto = UserDTO.builder()
                .id(1)
                .username(username)
                .firstname("John")
                .surname("Doe")
                .email("johndoe@example.com")
                .phoneNumber("123456789")
                .role(Role.USER)
                .build();
        when(userDTOMapper.apply(user)).thenReturn(expectedDto);
        
        UserDTO result = userService.findUser(username);
        
        assertEquals(expectedDto, result);
    }

    @Test
    public void testConvertToDto() {
        // Arrange
        User user = User.builder()
                .id(1)
                .username("testUser")
                .firstname("John")
                .surname("Doe")
                .email("johndoe@example.com")
                .phoneNumber("123456789")
                .role(Role.USER)
                .build();

        UserDTO expectedDto = UserDTO.builder()
                .id(1)
                .username("testUser")
                .firstname("John")
                .surname("Doe")
                .email("johndoe@example.com")
                .phoneNumber("123456789")
                .role(Role.USER)
                .build();

        when(modelMapper.map(user, UserDTO.class)).thenReturn(expectedDto);
        
        UserDTO result = userService.convertToDto(user);

        assertEquals(expectedDto, result);
    }

}

uqjltbpv

uqjltbpv2#

看来你已经有答案了
但这里是什么**“嘲笑”“存根”的意思在简单的话。通过模拟你的对象,你告诉编译器创建一个该对象的真实的示例的无效版本。因此,在使用该示例的方法时,您可能会得到NPE**,或者该方法可能会返回返回数据类型的默认值。因此,在这种情况下,stubbing就派上用场了。通过使用 Mockito 的when()方法,您将教 Mockito 如何处理方法调用,是否应该抛出异常,或者应该调用真实的的方法,或者不做任何事情。
把JUnit和Mockito想象成一个4岁的孩子。当你给那个孩子分配任务时,他可能无法自己操作,但他可能需要一些指令来做一些事情。

相关问题