【问题标题】:NullPointerException when testing service containing mocked JPA repository [duplicate]测试包含模拟 JPA 存储库的服务时出现 NullPointerException [重复]
【发布时间】:2020-03-18 09:52:56
【问题描述】:

我正在做我的第一个 Spring Boot 项目,但作为 Mockito 新手,我无法测试我的班级。 我需要检查下面的 findAndUpdateUser 方法是否正确更新了用户实体字段:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepo;

    public User findUser(String id) {
        return userRepo.findById(id);
    }

    public User findAndUpdateUser(String id) {
        User foundUser = findUser(id);
        //some update on foundUser fields
        return foundUser;
    }
}

为了测试,我需要模拟实体 bean,因为我在本地没有数据库。这是我的测试课:

@RunWith(MockitoJUnitRunner.class)
public class UpdateFieldsTest {
    @Mock
    private UserRepository userRepo;

    @Test
    public void test1() {
        User user = new User();
        user.setId("testId");
        //setting some other user fields

        Mockito.when(userRepo.findById("testId")).thenReturn(user);
        UserServiceImpl userService = new userServiceImpl();
        User returnedUser = userService.findAndUpdateUser("testId");

        //Checking if user field values are updated after findAndUpdate call
        Assert.xxx
        //other asserts
    }
}

但是这段代码在方法调用时给我抛出了一些 NullPointerException。我什至试图模拟 findUser 方法,但我仍然有错误......

我的方法不好吗?我应该如何测试我的方法?

欢迎任何帮助 谢谢大家

【问题讨论】:

  • 1.完整的堆栈跟踪通常有助于调试 NPE。 2. 你永远不会感染那种依赖。您应该通过构造函数或设置器将userRepo 传递给userService
  • 您正在实例化 UserServiceImpl,它会自动连接 UserRepository 我想?你不能那样做。如果你不让框架处理你的服务被实例化的方式,通过@Autowired注解表达的DI将不起作用。可能是NPE的原因。 Mockito 提供了一些机制来处理带有模拟实例的 DI。你可以看看@InjectMocksf.ex.
  • @Imaguest 是的。我将检查我不知道的 InjectMocks 注释。非常感谢!

标签: java spring mocking mockito


【解决方案1】:

使用这个实例化 UserServiceImpl userService = new userServiceImpl();使 UserRepo 为空;

你正在使用 mockito,所以你可以使用 @InjectMocks private UserServiceImpl; 并删除安装行。

【讨论】:

  • 哇,谢谢。所以 Mockito 只需通过注解自动将 UserRepo 依赖绑定到对应的服务上!那是强大的!再次感谢!
【解决方案2】:

模拟不会神奇地出现在您的对象内部。您需要手动注入它们。在您的测试中,在userService 内部,userRepo 将为空。您可以通过构造函数或 setter 注入依赖项。在您的测试中看起来像这样:

UserServiceImpl userService = new userServiceImpl(userRepo);

或者

UserServiceImpl userService = new userServiceImpl();
userService.setUserRepo(userRepo);

【讨论】:

  • 谢谢,我要试试这个
  • 可以分享 findAndUpdateUser 功能吗?我猜,在调用 findById 之后,你会调用另一个函数(save、saveOrUpdate ...)。在这种情况下,第二种方法返回 null,您应该模拟它。
  • findAndUpdateUser 基本上调用 findUser 然后通过 setter 更新 1 个用户字段(在本例中为 user.setLastConsultDate(now())然后返回对象
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多