Java 尝试在测试中使用方法时出现NullPointer错误
您好,我是Junit新手,目前正在使用Junit 5为此类编写单元测试:Java 尝试在测试中使用方法时出现NullPointer错误,java,spring,spring-boot,junit,Java,Spring,Spring Boot,Junit,您好,我是Junit新手,目前正在使用Junit 5为此类编写单元测试: @Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired UserRepository userRepository; @Override public UserDetails loadUserByUsername(String email) throws Usernam
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Optional<User> user = userRepository.findByEmail(email);
user.orElseThrow(() -> new UsernameNotFoundException("Not found: " + email));
return user.map(UserDetailsImpl::new).get();
}
}
我试图使userRepository.findByEmailemail方法返回可选用户以使错误消失我的尝试被注释掉,但我无法处理此问题。欢迎使用Stackoverflow UserDetailsServiceImpl中的UserRepository不会在单元测试中自动连接/注入,因为没有初始化spring上下文。您可以使用mock测试这种依赖关系。你可以查一下mockito。或者,您也可以尝试为测试初始化Spring上下文,但我不建议这样做 除了我的回答之外,我还有几个建议: 记住你的框架。它们不仅仅是魔法。了解spring是如何工作的,以及引擎盖下的自动连线注释是如何工作的 如果您是依赖项注入的新手,我强烈建议您使用它来解释基础知识 您已经收到一些提示您解决方案的注释。我相信他们正在试图帮助你,不仅仅是提供答案,而是帮助你自己发现问题 如果您需要一个使用mockito测试Spring Boot项目单元的示例,您可以检查
我希望这会有所帮助。如果您自己创建UserDetailsServiceImpl实例,并且不让Spring来做,则不会注入任何内容。这就是您在@BeforeAll方法中所做的,因为您使用的是基于字段的注入,您看不到这一点 如果您想继续使用这种注入方法,您需要让spring在测试中注入UserDetailsServiceImpl 为此,您需要将@SpringBootTest添加到测试类中:
class UserDetailsServiceImplTest {
private static UserDetailsServiceImpl userDetailsServiceImpl;
String email;
/*User mockedUser;
UserRepository userRepository;
UserDetails userDetails;*/
@BeforeAll
static void setup() {
userDetailsServiceImpl = new UserDetailsServiceImpl();
}
@Test
void testLoadUserByUsername() {
/*userRepository = mock(UserRepository.class);
mockedUser = mock(User.class);
Optional<User> user = Optional.of(mockedUser);
when(userRepository.findByEmail(email)).thenReturn(user);
assertEquals(userRepository.findByEmail(email), user);*/
UserDetails userDetails = userDetailsServiceImpl.loadUserByUsername(email);
assertTrue(userDetails instanceof UserDetails);
}
}
@SpringBootTest
class UserDetailsServiceImplTest {
@Autowired
private UserDetailsServiceImpl userDetailsServiceImpl;
}
但是,您似乎想要模拟UserRespository,对于单元测试来说,这是最好的选择。最简单、最干净的等待就是更新如何进行注入,并在此基础上更多地使用构造函数注入
@服务
公共类UserDetailsServiceImpl实现UserDetailsService{
私有最终用户存储库用户存储库;
公共用户详细信息服务ImplUserRepository用户存储库{
this.userRepository=userRepository
}
@凌驾
public UserDetails loadUserByUsernameString电子邮件引发UsernameNotFoundException{
可选用户=userRepository.findbyemailmail;
user.orelsetrow->new username notfoundexception not found:+电子邮件;
返回user.mapUserDetailsImpl::new.get;
}
}
并将您的测试更改为一个简单的单元测试:
class UserDetailsServiceImplTest {
private UserDetailsServiceImpl userDetailsServiceImpl;
private UserRepository userRepository;
@BeforeEach
void setup() {
userRepository = mock(UserRepository.class)
userDetailsServiceImpl = new UserDetailsServiceImpl(userRepository);
}
@Test
void testLoadUserByUsername() {
mockedUser = mock(User.class);
Optional<User> user = Optional.of(mockedUser);
when(userRepository.findByEmail(email)).thenReturn(user);
assertEquals(userRepository.findByEmail(email), user);
UserDetails userDetails = userDetailsServiceImpl.loadUserByUsername(email);
assertTrue(userDetails instanceof UserDetails);
}
}
正如@bhdrkn所建议的那样,您需要阅读更多关于框架和依赖注入的内容。还有关于单元测试。我看不出您到底在哪里出错,但您可能无法很好地自动连接userRepository。你能检查一下你确定userRepository正在自动连接吗?您还可以提供更多的堆栈跟踪吗?您至少需要@RunWithSpringRunner.class@SpringBootTestclasses={…}您在测试类上使用了这些注释吗?@Shoshi我已经添加了这些注释,我仍然得到相同的注释error@Ascalonian当我运行应用程序时,它工作正常,所以我确信userRepository正在自动连接
class UserDetailsServiceImplTest {
private UserDetailsServiceImpl userDetailsServiceImpl;
private UserRepository userRepository;
@BeforeEach
void setup() {
userRepository = mock(UserRepository.class)
userDetailsServiceImpl = new UserDetailsServiceImpl(userRepository);
}
@Test
void testLoadUserByUsername() {
mockedUser = mock(User.class);
Optional<User> user = Optional.of(mockedUser);
when(userRepository.findByEmail(email)).thenReturn(user);
assertEquals(userRepository.findByEmail(email), user);
UserDetails userDetails = userDetailsServiceImpl.loadUserByUsername(email);
assertTrue(userDetails instanceof UserDetails);
}
}