使用Mockito的弹簧引导服务层单元测试 - 模拟数据已无效



我正在尝试使用junit ockito测试服务层,但是每次运行时,返回对象都会被否定。

更多信息:

  • 用户介绍是一个普通的弹簧数据存储库,扩展了crudrepository。
  • 用户是一个普通的JPA实体。

和测试:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
    @Mock
    private UserRepository userRepository;
    @InjectMocks
    private UserService userService = new UserService();
    private User user;
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }
    @Test
    public void tesGetUserIdStatus() {
        // given
        user = new User();
        user.setUserName(userName);
        user.setUserId(userId);
        User newUser = new User();
        // when
        Mockito.when(userRepository.findByUserId(userId)).thenReturn(newUser);
        User result = userService.getUserById(user);
        // then
        Assert.assertEquals(newUser, user);
    }
}

该测试最终将在实际正确时将预期的对象值无效。

我想测试的服务部分如下:

@Component
public class UserService {
    private final UserRepository userRepository;
    public UserService(UserRepository userRepository) {
    this.userRepository = userRepository;
}
    public User getUserById(User user) throws EntityNotFoundException {

        String userId = user.getUserId();
        user = userRepository.findByUserId(userId);
        return user;
    }
...

我还看到了一个设计问题,除了摩知道的不当用户。@InjectMocks不是一个不错的选择。这是有缺陷的,这是他们的javadocs所说的。

  • Mockito将尝试仅通过构造函数注入模拟 注射, *设置器注入或按顺序注入财产注入 如下面所描述的。*如果以下任何策略失败,则 Mockito 不会报告失败;*即你将有 自己提供依赖项。

我认为应该对其进行弃用,以便开发人员可以很好地注入构造函数。看看这种方法;

重构UserService,因此您可以通过UserService'S 构造函数注入UserRepository。例如:https://docs.spring.io/spring-boot/docs/current/referent/reference/html/usis--boot-spring-bean-bean-bean-and-depportency-injoction.html

然后

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
    @Mock
    private UserRepository userRepository;

    private UserService userService;
    private User user;
    @Before
    public void setUp() throws Exception {
       userService = new UserService(userRepository);
    }
    @Test
    public void tesGetUserIdStatus() {
        //your test code
    }

这是一个很好的做法,您可以用正确的模拟和固执孤立地测试逻辑(服务,帮助者等)。

但是,如果要在春季IOC容器中验证正确的资源注入,并且想进行诸如验证之类的操作,则应考虑适当的弹簧/春季启动测试。看看官方春季测试文档-https://docs.spring.io/spring-boot/docs/current/current/referent/html/boot-features-testing.html

findByUserId(UserId)您的意思是findByUserId(userId),并且 Assert.assertEquals(newUser, user)您是指Assert.assertEquals(result, user)?值用户名和UserId从何而来?

,请不要使用@InjectMocks注入userService

而是尝试一下:

@Autowired
private UserService userService;

或至少

@InjectMock
private UserService userService;

您的测试可能会失败,因为用户服务中的存储库无法正确注入,并且返回的结果将为 null

您的测试中有一些问题:

  • UserService由Mockito(@InjectMocks)实例化 - 不要使用新的UserService实例初始化它 - 这就是您获得NPE
  • 的原因
  • 由于您正在使用MockitoJUnitRunner,因此您无需明确调用MockitoAnnotations.initMocks
  • when(userRepository.findByUserId(UserId))-什么是UserId
  • 呼叫Mockito.when()应该是给定部分的一部分
  • 在当时的部分中,您应该主张您在章节中获得的价值

最新更新