【问题标题】:Using BCryptPasswordEncoder in Unit Test returns a null value在单元测试中使用 BCryptPasswordEncoder 返回一个空值
【发布时间】:2022-11-15 06:41:22
【问题描述】:

我在 Spring boot 应用程序上学习使用 JUnit 和 Mockito 进行单元测试,我有一个要测试的注册方法,在我的测试方法中我创建了一个用户,但我看到使用 .encode 时密码的值始终为 null (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 的输出是这样的,我不确定在测试该方法时如何处理密码加密。

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

【问题讨论】:

    标签: java testing junit mockito


    【解决方案1】:

    您在测试中的服务:

        @Mock
        private UserRepository userRepository;
    
        @Mock
        public PasswordEncoder passwordEncoder;
    

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

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

    问题是您没有在passwordEncoder 中存根任何方法,因此它的方法将什么都不做并返回null

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

    【讨论】:

      猜你喜欢
      • 2022-01-23
      • 1970-01-01
      • 2021-04-02
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多