Jack_Russell
Jack_Russell

Reputation: 343

Spring Data repository can't autowire

I'm creating a new Spring Boot app from the scratch and want to write tests for it. I've just implemented authentication into my app and want to learn how roles work.

When I use my UserRepository in the authentication process, everything works as it should. However, when I want to use UserRepository in tests, it says that the object is null, the same one that's OK when I use it in the app code. Why is that? Here's the code.

Security configuration class:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PowderizeUserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .httpBasic()
                .and()
                .logout().permitAll();
    }

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManager) {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationManager.authenticationProvider(authenticationProvider);
    }

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

}

User class:

@Entity
@Table(name = "USERS")
@NoArgsConstructor
@Getter
public class User extends BaseEntity {

    private String firstName;
    private String lastName;
    private String emailAddress;
    private String nickname;
    private String password;
    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private boolean enabled;
    @ManyToMany(mappedBy = "users_roles")
    private Set<Role> roles;
}

Repository:

public interface UserRepository extends CrudRepository<User, Long> {

    public Optional<User> findByEmailAddress(String email);
}

UserDetailsService implementation class, that uses the repository with no problems:

@Service
public class PowderizeUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
                return new PowderizePrincipal(
                        userRepository.findByEmailAddress(email)
                                .orElseThrow(() -> new UsernameNotFoundException("User '" + email + "' not found."))
                );
    }
}

And the test class that returns NullPointerException:

@SpringBootTest
public class UsersAndRolesTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void ww(){
        assertThat(userRepository, notNullValue());
    }

    @Test
    public void userExistsInDatabase(){
        assertThat(userRepository.findByEmailAddress("[email protected]").isPresent(), notNullValue());
    }

}

I've tried using annotations like @Repository, @EnableJpaRepositories, actually every solution I've found. IntelliJ also highlights the userRepository with "Could not autowire. No beans of 'UserRepository' type found."

Upvotes: 0

Views: 480

Answers (2)

Jack_Russell
Jack_Russell

Reputation: 343

I've found the solution, guided by vanillaSugar's answer. What I was lacking was the @RunWith(SpringRunner.class) annotation, but it was not enough. I've realized that the problem was also connected to the package the test suite was located. I didn't add the package line of code in the question, and it was the part of the problem as well.

From what I've found, @SpringBootApplication scans for components below it in the package hierarchy in the app. Just adding @RunWith annotation led me to this problem with another exception: java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test.

What I also had to do is to move my test class from previous package - security.UsersAndRolesTest to com.powderize.security.UsersAndRolesTest, which "mirrors" the packages in the app code. Probably obvious for more advanced Spring developers, but took me a while to discover it.

Upvotes: 2

vanillaSugar
vanillaSugar

Reputation: 551

Add this annotation to your UsersAndRolesTest class

@RunWith(SpringRunner.class)

Upvotes: 2

Related Questions