Параметр 0 метода setUserService при запуске тестового контроллера

У меня есть приложение Spring Security. Я добавил пользовательский SpringDataUserDetailsService implements UserDetailsService. Автопроводка setUserService.

public class SpringDataUserDetailsService implements UserDetailsService {

    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = userService.findByEmail(username);

        if (user == null) {
            throw new UsernameNotFoundException(username);
        }

        return new org.springframework.security.core.userdetails.User(
                user.getEmail(),
                user.getPassword(),
                convertAuthorities(user.getRoles()));
    }

    private Set<GrantedAuthority> convertAuthorities(Set<Role> userRoles) {
        Set<GrantedAuthority> authorities = new HashSet<>();
        for (Role ur : userRoles) {
            authorities.add(new SimpleGrantedAuthority(ur.getRole()));
        }
        return authorities;
    }
}
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    User findByEmail(String email);
}
@Service
public class UserService {

    private static final String DEFAULT_ROLE = "ROLE_USER";
    private final UserRepository userRepository;
    private final RoleRepository roleRepository;
    private final PasswordEncoder passwordEncoder;

    public UserService(UserRepository userRepository, RoleRepository roleRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.roleRepository = roleRepository;
        this.passwordEncoder = passwordEncoder;
    }

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

    public void registerNewUserAccount(User user) {
        if (emailExist(user.getEmail())) {
            throw new UserAlreadyExistException("There is an account with that email address: "
            + user.getEmail());
        }

        // set default role
        Role userRole = roleRepository.findRoleByRole(DEFAULT_ROLE);
        user.getRoles().add(userRole);

        // set hash password
        user.setPassword(passwordEncoder.encode(user.getPassword()));

        // save
        userRepository.save(user);
    }

    public User findByEmail(String email) {
        return userRepository.findByEmail(email);
    }

    private boolean emailExist(String email) {
        return userRepository.findByEmail(email) != null;
    }
}

Я проверил через браузер, и он работает нормально. Я могу зарегистрировать нового пользователя (в базу данных), а затем войти в приложение. Теперь я хочу написать тест для CustomerController, но получил ошибку. Если я удаляю Autowired setUserService тест пройден, но я не могу зарегистрировать нового пользователя. Где мне нужно найти проблему?

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customUserDetailsService': Unsatisfied dependency expressed through method 'setUserService' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '.service.UserService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

@ExtendWith(SpringExtension.class)
@WebMvcTest(CustomerController.class)
class CustomerControllerTest {

    @MockBean
    private CustomerService customerService;

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext context;

    @BeforeEach
    public void setup() {
        mockMvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity())
                .build();
    }

    @WithMockUser(value = "spring")
    @Test
    void shouldReturnViewWithPrefilledData() throws Exception {

        Customer customer = new Customer();
        customer.setId(1L);
        customer.setCustomerName("customer Name");

        when(customerService.getAllCustomers()).thenReturn(List.of(customer));

        this.mockMvc.perform(MockMvcRequestBuilders.get("/customer/list"))
                .andExpect(status().isOk())
                .andExpect(view().name("customer/customer-list"))
                .andExpect(MockMvcResultMatchers.model().attributeExists("customers"));

    }
}
Основы программирования на Java
Основы программирования на Java
Java - это высокоуровневый объектно-ориентированный язык программирования, основанный на классах.
Концепции JavaScript, которые вы должны знать как JS программист!
Концепции JavaScript, которые вы должны знать как JS программист!
JavaScript (Js) - это язык программирования, объединяющий HTML и CSS с одной из основных технологий Всемирной паутины. Более 97% веб-сайтов используют...
0
0
22
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы должны добавить

@Import({UserService.class})

вам тестовый класс. Результат будет

@ExtendWith(SpringExtension.class)
@WebMvcTest(CustomerController.class)
@Import({UserService.class})
class CustomerControllerTest {

Вы аннотировали свой класс с помощью «WebMvcTest». В этом случае spring не полностью запускает весь свой контекст. Например, инициализация компонента выполняется только для контроллера. Если вы хотите, чтобы все было инициализировано (потому что вы ленивы или потому что ваш UserService имеет больше зависимостей, которые необходимо импортировать вручную), вы можете заменить

@WebMvcTest(CustomerController.class)

с

@SpringBootTest

это, однако, займет больше времени, чтобы запустить ваш unitTest, так как он должен инициализировать больше контекста

Другие вопросы по теме