繁体   English   中英

在单元测试中使用 BCryptPasswordEncoder 返回 null 值

[英]Using BCryptPasswordEncoder in Unit Test returns a null value

我正在 Spring 启动应用程序上学习 JUnit 和 Mockito 的单元测试,我有一个要测试的注册方法,在我的测试方法中我创建了一个用户,但我看到密码的值始终是 null using.encode (mypassword),导致断言错误。


UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    public UserServiceImpl(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }


    @Override
    public User register(User user) {


         Role role = roleService.findByName(ERole.ROLE_USER);

         Set<Role> roleSet = new HashSet<>();
         user.setFullName(user.getFullName());
         user.setEmailAddress(user.getEmailAddress());
         user.setPassword(passwordEncoder.encode(user.getPassword()));
         user.setConfirmPassword("");
         user.setEmailVerified(true);
         roleSet.add(role);
         user.setRoles(roleSet);

         if(userRepository.existsByEmailAddress(user.getEmailAddress())) {
             throw new EmailAlreadyExistsException("Account already exists with this email");
         }
        return userRepository.save(user);
    }



}


UserServiceImplTest.java

@ExtendWith(MockitoExtension.class)
class UserServiceImplTest {

    @InjectMocks
    private UserServiceImpl userService;

    @Mock
    private UserRepository userRepository;

    @Mock
    public PasswordEncoder passwordEncoder;

  

   @BeforeEach
    void setUp() {
        userService = new UserServiceImpl(userRepository, passwordEncoder);
    }

  @Test
    void testIfUserCanRegisterSuccessfully() {

        User user = new User(1, "admin", "admin@gmail.com", passwordEncoder.encode("password"));

        when(userRepository.save(any())).thenReturn(user);
        User theUser = userService.register(user);


        System.out.println("theUser: " + theUser);

        assertNotNull(theUser);
        assertEquals(1, theUser.getId());
        assertEquals("admin@gmail.com", theUser.getEmailAddress());
        assertTrue(passwordEncoder.matches("password", theUser.getPassword()));
    }

}


安全配置.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Value("${spring.security.ant.matchers}")
    private String[] securityAntMatchers;
    

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private JwtAuthenticationEntryPoint authenticationEntryPoint;

    @Bean
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
        return new JwtAuthenticationTokenFilter();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }



    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable().formLogin().disable().httpBasic().disable();

        http
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
            .and()
            .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);

        http
            .authorizeRequests()
            .antMatchers(securityAntMatchers)
            .permitAll()
            .anyRequest()
            .authenticated();
    }

}


theUser的output是这个,测试方法时不知道密码加密怎么处理。

theUser: User{id=1, fullName='admin', emailAddress='admin@gmail.com', dateJoined=Tue Nov 15 00:06:01 CAT 2022, emailVerified=true, password='null'}


已编辑



    @BeforeEach
    void setUp() {
        // Instantiating password encoder before every test, now I get the output
        this.passwordEncoder = new BCryptPasswordEncoder();
        userService = new UserServiceImpl(userRepository, passwordEncoder);


    }

  @Test
    void testIfUserCanRegisterSuccessfully() {
        User user = new User(1, "admin", "admin@gmail.com","password");

        when(userRepository.save(any())).thenReturn(user);
        User created = userService.register(user);

        assertEquals(created.getPassword(), user.getPassword());
        assertEquals(created.getEmailAddress(), user.getEmailAddress());
        verify(userRepository).save(any());
    }

您在测试中的服务:

    @Mock
    private UserRepository userRepository;

    @Mock
    public PasswordEncoder passwordEncoder;

是模拟,这意味着它们实际上不会做任何事情,除非您通过存根方法明确告诉它们要做什么,就像您在这里所做的那样:

       when(userRepository.save(any())).thenReturn(user);

问题是您没有在passwordEncoder中添加任何方法,因此它的方法将不执行任何操作并返回null

此外,您似乎正在对密码进行两次编码(一次在测试中,一次在register方法中),即使使用适当的存根,这也可能导致错误

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM