Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 尝试在测试中使用方法时出现NullPointer错误_Java_Spring_Spring Boot_Junit - Fatal编程技术网

Java 尝试在测试中使用方法时出现NullPointer错误

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

您好,我是Junit新手,目前正在使用Junit 5为此类编写单元测试:

@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);
    }
}