1

I have a problem when testing a method with using passwordencoder:

Cannot invoke "org.springframework.security.crypto.password.PasswordEncoder.encode(java.lang.CharSequence)" because the return value of "com.store.restAPI.user.UserConfig.passwordEncoder()" is null`

Thats my test class method:

    @ExtendWith(MockitoExtension.class)
    class UserServiceTest {

        private UserService underTest;
        @Mock
        private  UserRepository userRepository;
        @Mock
        private  UserConfig userConfig;

        @BeforeEach
        void setUp(){
            underTest = new UserService(userRepository, userConfig);
        }

        @Test
        void itShouldFindAllUsers() {
            //when
            underTest.findAll();

            //then
            verify(userRepository).findAll();

        }

        @Test
        void addNewUser() {
            //given
            User expected = new User(
                    "[email protected]",
                    "123"
            );

            //when
            underTest.addNewUser(expected);

            //then
            ArgumentCaptor<User> userArgumentCaptor = 
    ArgumentCaptor.forClass(User.class);
            verify(userRepository).save(userArgumentCaptor.capture());
            User capturedUser = userArgumentCaptor.getValue();
            assertThat(capturedUser).isEqualTo(expected);
        }

        @Test
        @Disabled
        void loginUser() {
        }
    }

And thats UserService method that i want to test:

    @Service
    public class UserService {

        private final UserRepository userRepository;
        private final UserConfig userConfig;

        @Autowired
        public UserService(UserRepository userRepository, UserConfig userConfig) {
            this.userRepository = userRepository;
            this.userConfig = userConfig;
        }

        public List<User> findAll() {
            return userRepository.findAll();
        }

        public void addNewUser(User user) {
            Optional<User> userOptional = userRepository.findUserByEmail(user.getEmail());
            if(userOptional.isPresent()){
                throw new IllegalStateException("email taken");
            }
            String hashedPassword = userConfig.passwordEncoder().encode(user.getPassword());
            user.setPassword(hashedPassword);
            userRepository.save(user);
        }

        public void loginUser(User user){
            Optional<User> userOptional = userRepository.findUserByEmail(user.getEmail());
            if(userOptional.isEmpty()){
                throw new IllegalStateException("no account under that email");
            }
            else 
    if(!userConfig.passwordEncoder().matches(user.getPassword(), 
    userOptional.get().getPassword())){
                throw new IllegalStateException("wrong password");
            }
        
    //!userOptional.get().getPassword().equals(user.getPassword())
         }
    }

Password encoder is a bean in class UserConfig.

    @Configuration
    public class UserConfig {

        @Bean
        CommandLineRunner commandLineRunnerUser(UserRepository repository) {
            return args -> {
                User iza = new User(
                        "[email protected]",
                    
    "$2a$10$U87IFlm9DYXRITUSnfdfDuknz8ijJCcK9UVR4D4kUDu7w13zPuURK"
                );

                User andrzej = new User(
                        "[email protected]",
                    
    "$2a$10$fmYOxyvWBr47wAg1m/ryy.G4J1PbT2LRj6m7oENkBtEsGocansE9G"
                );

                User tomek = new User(
                        "[email protected]",
                    
    "$2a$10$chrySvbZSZcje4r3Q0PZv.FrO6/k2WvM42GX3x2EmySZc/dAA2glC"
                );

                repository.saveAll(
                        List.of(iza,andrzej,tomek)
                );
            };
        }

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

Do i need to create another method with password encoder inside my test class? I don't know what am i doing wrong. Why does it say that result is null? Does someone know what am i doing wrong?

3
  • Please don't use images of code. If we want to test it for ourselves, we now have to completely type it ourselves. Commented Aug 2, 2022 at 10:27
  • You are using mocks the default of a mock is to return null when no behavior is present. Commented Aug 2, 2022 at 10:55
  • what does it mean no behavior is present? Sorry i don't understand i'm new to mock. Commented Aug 2, 2022 at 10:59

1 Answer 1

3

In your UserServiceTest, you're currently mocking UserConfig. A mock is basically an implementation that has no behavior at all. This means that userConfig.passwordEncoder() will return null in your test.

To solve this, you have to tell Mockito what the behavior is of your UserConfig class. For example:

Mockito.when(userConfig.passwordEncoder()).thenReturn(new BCryptPasswordEncoder());

This also allows you to use a different (eg. a dummy) password encoder in your unit tests.


Another suggestion, unrelated to your question, is that you can directly autowire PasswordEncoder in your UserService in stead of autowiring UserConfig. This works because you annotated UserConfig with @Configuration and UserConfig.passwordEncoder() with @Bean:

 @Service
public class UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder; // Change this

     // And change the constructor parameter
    @Autowired
    public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder; // And this
    }

    // The rest of your code...
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.