Home > Back-end >  Error creating bean with name 'securityConfig' defined in file
Error creating bean with name 'securityConfig' defined in file

Time:07-26

I´m trying to make a Unit test of the methods of my project which contains spring security. When I run the project it works normally, but when I try to unit test the methods it gives me this error.

Description:
Pramenter 0 of constructor in ...config.secutityConfig required a bean of type 'org.springframeword.security.userdetails.UserDetailsService' that could not be found

Action:
Consider defining a bean of type 'org.springframework.security.core.userdetails.UserDetailsService in your configuration'

This is my SecurityConfig.java code:

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private final UserDetailsService userDetailsService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;

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


@Override
protected void configure(HttpSecurity http) throws Exception {
    CustomAuthenticationFilter customAuthenticationFilter = new CustomAuthenticationFilter(authenticationManagerBean());
    http.csrf().disable();
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    http.authorizeRequests().antMatchers(GET, "/user/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(POST, "/user/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(PUT, "/user/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(DELETE, "/user/**").hasAnyAuthority("ADMIN");

    http.authorizeRequests().antMatchers(GET, "/category/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(POST, "/category/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(PUT, "/category/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(DELETE, "/category/**").hasAnyAuthority("ADMIN");

    http.authorizeRequests().antMatchers(GET, "/product/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(POST, "/product/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(PUT, "/product/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(DELETE, "/product/**").hasAnyAuthority("ADMIN");

    http.authorizeRequests().antMatchers(GET, "/shoppingcart/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(POST, "/shoppingcart/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(PUT, "/shoppingcart/**").hasAnyAuthority("ADMIN");
    http.authorizeRequests().antMatchers(DELETE, "/shoppingcart/**").hasAnyAuthority("ADMIN");

    http.authorizeRequests().antMatchers(GET, "/product/**").hasAnyAuthority("USER");

    http.authorizeRequests().anyRequest().authenticated();
    http.addFilter(customAuthenticationFilter);
    http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}

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

}

This is the test I'm trying to make, it's basically to save a category in the DB.

@WebMvcTest(controllers = CategoryRest.class)
public class CategoryRestTest extends AbstractUnitRestTest {

@MockBean
private CategoryService categoryService;


@Test
public void saveCategory() throws Exception {
    CreateCategoryCmd cmd = new CreateCategoryCmd("Tehnika", "TV, USB", Collections.emptySet());
    String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(cmd);
    Category category = CategoryBuilder.categoryBelaTehnika();

    doReturn(category).when(categoryService).save(any(CreateCategoryCmd.class));

    mockMvc.perform(post("/category/save")
            .contentType(MediaType.APPLICATION_JSON)
            .content(jsonInString)).andDo(print())
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name").value(category.getName()));
}

And this is my Userdetails:

@Service
@Transactional
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService, UserDetailsService {

private final static Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
private final UserDAO userDAO;
private final PayPalAccountDAO payPalAccountDAO;
private final RoleDao roleDao;
private final ShoppingCartDAO shoppingCartDAO;
private final PasswordEncoder passwordEncoder;


@Override
@Transactional
public User save(CreateUserCmd cmd) throws ServiceException {
    User user = UserMapper.INSTANCE.createUserCmdToUser(cmd);
    List<Role> roles = new ArrayList<>();
    List<Role> role = new ArrayList<>();
    Set<Role> ro = new HashSet<>();
    roles = roleDao.findAll();
    role.add(roles.get(0));
    ro.addAll(role);
    try {
        user.setRoles(ro);
        user.setPassword(passwordEncoder.encode(cmd.getPassword()));
        user = userDAO.save(user);
    } catch (DAOException e) {
        LOGGER.error(null, e);
        throw new ServiceException(ErrorCode.ERR_GEN_001, "Saving of user failed!", e);
    }
    return user;
}

@Override
public List<UserResult> findAll() {
    return UserMapper.INSTANCE.listUserToListUserResult(userDAO.findAll());
}

@Override
public UserInfo findById(Long id) {
    return UserMapper.INSTANCE.userToUserInfo(userDAO.findOne(id));
}

@Override
public void addAccount(PayPalAccount payPalAccount, User user) throws ServiceException{
    try{
        payPalAccount.setUserID(user);
        payPalAccountDAO.save(payPalAccount);
    } catch (DAOException e){
        LOGGER.error(null, e);
        throw new ServiceException(ErrorCode.ERR_GEN_001, "creating account failed");
    }
}

@Override
public void addCart(ShoppingCart shoppingCart, User user) throws ServiceException {
    try{
        shoppingCart.setUser(user);
        shoppingCart.setStatus(Status.NEW);
        shoppingCart.setPrice(new BigDecimal(0));
        shoppingCartDAO.save(shoppingCart);
    } catch (DAOException e) {
        LOGGER.error(null, e);
        throw new ServiceException(ErrorCode.ERR_GEN_001, "creating cart failed ");
    }
}

@Override
public void addRole(addRoleCmd cmd) throws ServiceException {
    User user;
    try{
        user = userDAO.findOne(cmd.getId());
        if(user == null){
            throw new ServiceException(ErrorCode.ERR_GEN_002);
        }
        UserMapper.INSTANCE.addingRoletoUser(user, cmd);
        user.getRoles().addAll(cmd.getRoles().stream()
                .map(v ->{
                    Role rr = roleDao.findOne(v.getId());
                    rr.getUser().add(user);
                    return rr;
                }).collect(Collectors.toSet()));
        userDAO.merge(user);
    }catch (DAOException e){
        LOGGER.error(null, e);
        throw new ServiceException(ErrorCode.ERR_GEN_001, "failed while adding new role", e);
    }
}


@Override
public void update(UpdateUserCmd cmd) throws ServiceException {
    User user;
    try {
        // check if entity still exists
        user = userDAO.findOne(cmd.getId());
        if (user == null) {
            throw new ServiceException(ErrorCode.ERR_GEN_002);
        }

        UserMapper.INSTANCE.updateUserCmdToUser(user, cmd);
        PayPalAccount palAccount = cmd.getPayPalAccount();
        Set<ShoppingCart> shoppingCarts = cmd.getShoppingCarts();

        for (ShoppingCart cart: shoppingCarts) {
            addCart(cart, user);
        }
        user.setAccount(palAccount);
        addAccount(palAccount, user);
        userDAO.merge(user);
    } catch (DAOException e) {
        LOGGER.error(null, e);
        throw new ServiceException(ErrorCode.ERR_GEN_001, "Update of user failed!", e);
    }
}


@Override
public void delete(Long id) throws ServiceException {
    User user = userDAO.findOne(id);
    if (user != null) {
        try {
            userDAO.delete(user);
        } catch (DAOException e) {
            LOGGER.error(null, e);
            throw new ServiceException(ErrorCode.ERR_GEN_001, "Delete of user failed!", e);
        }
    } else {
        throw new ServiceException(ErrorCode.ERR_CAT_001, "User does not exist!");
    }
}



@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userDAO.findByUsername(username);
    if(user == null){
        LOGGER.error("User not found");
        throw new UsernameNotFoundException("User not found in the database");
    } else{
        LOGGER.info("User found in the DB");
    }
    Collection<SimpleGrantedAuthority> authorities = new HashSet<>();
    user.getRoles().forEach(role -> {
        authorities.add(new SimpleGrantedAuthority(role.getName()));
    });
    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
}

Any suggestions?

CodePudding user response:

The problem here is that if you read the documentation for WebMvcTest it says straight out in the second paragraph:

Using this annotation will disable full auto-configuration and instead apply only configuration relevant to MVC tests (i.e. @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver beans but not @Component, @Service or @Repository beans).

Which means it will only load a subsection of the application.

The code provided shows

@WebMvcTest(controllers = CategoryRest.class)

Which will only load the defined controller and the rest defined in the documentation.

The UserDetailsService is annotated as a @Service which means it will NOT be loaded at startup.

If you want to load the application fully you need to use @SpringBootTest in conjuction with other annotations for instance @AutoConfigureMockMvc or @AutoConfigureWebTestClientdepending on which client to use.

All of this is properly documentated with easy to read instructions in the spring boot documentation testing chapter.

  • Related