Spring Test returning 401 for unsecured URLs

后端 未结 4 1580
北荒
北荒 2020-12-07 00:38

I am using Spring for MVC tests

Here is my test class

@RunWith(SpringRunner.class)
@WebMvcTest
public class ITIndexController {

    @Autowired
    W         


        
4条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-07 01:22

    I had an some problem and solve the issue with the help of the answers here and @Sam Brannen comment.

    You probably don't need to use @ContextConfiguration. Simply adding @Import(SecurityConfig.class) should typically suffice.

    To simplify and update the answers a bit more I want to share how i fix it in my spring-boot2 project.

    I want to test below endpoint.

    @RestController
    @Slf4j
    public class SystemOptionController {
    
      private final SystemOptionService systemOptionService;
      private final SystemOptionMapper systemOptionMapper;
    
      public SystemOptionController(
          SystemOptionService systemOptionService, SystemOptionMapper systemOptionMapper) {
        this.systemOptionService = systemOptionService;
        this.systemOptionMapper = systemOptionMapper;
      }
    
      @PostMapping(value = "/systemoption")
      public SystemOptionDto create(@RequestBody SystemOptionRequest systemOptionRequest) {
        SystemOption systemOption =
            systemOptionService.save(
                systemOptionRequest.getOptionKey(), systemOptionRequest.getOptionValue());
        SystemOptionDto dto = systemOptionMapper.mapToSystemOptionDto(systemOption);
        return dto;
      }
    }
    

    All service methods must be interface otherwise application context can't be initialized. You can check my SecurityConfig.

    @Configuration
    @EnableWebSecurity
    @EnableResourceServer
    @EnableGlobalMethodSecurity(securedEnabled = true)
    public class SecurityConfig extends ResourceServerConfigurerAdapter {
    
        @Autowired
        private ResourceServerTokenServices resourceServerTokenServices;
    
        @Override
        public void configure(final HttpSecurity http) throws Exception {
            if (Application.isDev()) {
                http.csrf().disable().authorizeRequests().anyRequest().permitAll();
            } else {
                http
                        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                        .and()
                        .authorizeRequests().regexMatchers("/health").permitAll()
                    .antMatchers("/prometheus").permitAll()
                    .anyRequest().authenticated()
                        .and()
                        .authorizeRequests()
                        .anyRequest()
                        .permitAll();
                http.csrf().disable();
            }
        }
    
        @Override
        public void configure(final ResourceServerSecurityConfigurer resources) {
            resources.tokenServices(resourceServerTokenServices);
        }
    }
    

    And below you can see my SystemOptionControllerTest class.

    @RunWith(SpringRunner.class)
    @WebMvcTest(value = SystemOptionController.class)
    @Import(SecurityConfig.class)
    public class SystemOptionControllerTest {
    
      @Autowired private ObjectMapper mapper;
    
      @MockBean private SystemOptionService systemOptionService;
      @MockBean private SystemOptionMapper systemOptionMapper;
      @MockBean private ResourceServerTokenServices resourceServerTokenServices;
    
      private static final String OPTION_KEY = "OPTION_KEY";
      private static final String OPTION_VALUE = "OPTION_VALUE";
    
      @Autowired private MockMvc mockMvc;
    
      @Test
      public void createSystemOptionIfParametersAreValid() throws Exception {
        // given
    
        SystemOption systemOption =
            SystemOption.builder().optionKey(OPTION_KEY).optionValue(OPTION_VALUE).build();
    
        SystemOptionDto systemOptionDto =
            SystemOptionDto.builder().optionKey(OPTION_KEY).optionValue(OPTION_VALUE).build();
    
        SystemOptionRequest systemOptionRequest = new SystemOptionRequest();
        systemOptionRequest.setOptionKey(OPTION_KEY);
        systemOptionRequest.setOptionValue(OPTION_VALUE);
        String json = mapper.writeValueAsString(systemOptionRequest);
    
        // when
        when(systemOptionService.save(
                systemOptionRequest.getOptionKey(), systemOptionRequest.getOptionValue()))
            .thenReturn(systemOption);
        when(systemOptionMapper.mapToSystemOptionDto(systemOption)).thenReturn(systemOptionDto);
    
        // then
        this.mockMvc
            .perform(
                post("/systemoption")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(json)
                    .accept(MediaType.APPLICATION_JSON))
            .andDo(print())
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(content().string(containsString(OPTION_KEY)))
            .andExpect(content().string(containsString(OPTION_VALUE)));
      }
    }
    

    So I just need to add @Import(SecurityConfig.class) to my mvc test class.

提交回复
热议问题