简体   繁体   中英

SpringBoot Rest Controller Integration test always gives 401 unauthorized

I have a rest controller, which has simple CRUD operations. I am trying to write integration test.

Below is my RestController:

package com.gasx.corex.scheduler.controller;

import java.awt.*;
import java.util.List;

import com.gasx.corex.scheduler.service.SchedulerJobServiceI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.gasx.corex.ext.scheduler.domain.SchedulerJob;
import com.gasx.corex.scheduler.service.SchedulerJobService;


@RestController
@RequestMapping("/gasx/restscd")
public class SchedulerJobController {

    @Autowired
    private SchedulerJobServiceI schedulerJobService;

    @RequestMapping(method = RequestMethod.GET , path="/getschedulerjobs" , produces= MediaType.APPLICATION_JSON_VALUE)
    public List<SchedulerJob> getAllSchedulerJobs() {
        return schedulerJobService.getAllSchedulerJobs();
    }

    @RequestMapping(method = RequestMethod.POST, value = "/addschedulerjob")
    public void addSchedulerJob(@RequestBody SchedulerJob schedulerJob) {
        schedulerJobService.addSchedulerJob(schedulerJob);
    }

    @RequestMapping(method = RequestMethod.POST, value = "/updateschedulerjob")
    public void updateSchedulerJob(@RequestBody SchedulerJob schedulerJob) {
        schedulerJobService.updateSchedulerJob(schedulerJob);
    }

    @RequestMapping(method = RequestMethod.POST, value = "/deleteschedulerjob")
    public void deleteSchedulerJob(@RequestBody SchedulerJob schedulerJob) {
        schedulerJobService.deleteSchedulerJob(schedulerJob);
    }
}

I have written Integration test for all of the endpoints in RestController

Integration test class :-

package com.gasx.corex.ext.scheduler.integrationtest.domain;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gasx.corex.base.configuration.CoreConfiguration;
import com.gasx.corex.ext.scheduler.domain.SchedulerJob;
import com.gasx.corex.ext.scheduler.domain.utils.SchedulerJobType;


import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.http.HttpHeaders;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;
import sun.security.krb5.internal.Ticket;
import org.springframework.http.HttpMethod;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

import java.io.IOException;
import java.util.Base64;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT  , properties = {
        "management.server.port=0", "management.context-path=/admin" ,"security.basic.enabled=false"} )
@EnableAutoConfiguration
@ContextConfiguration( classes = {CoreConfiguration.class  } )
@AutoConfigureMockMvc
public class SchedulerJobTestInt {

    @LocalServerPort
    private int port  ;


    @Autowired
    private TestRestTemplate testRestTemplate;

    @Autowired
    WebApplicationContext context;

    @Autowired
    private MockMvc mockMvc;


    @Before
    public void setUp() {
        this.mockMvc = MockMvcBuilders
                .webAppContextSetup(context)
                .build();
    }

    @Test
    public void getAllSchedulerJobsIntTest() throws Exception {
        ResponseEntity<String> response = testRestTemplate.getForEntity("http://localhost:" + port +"/gasx/restscd/getschedulerjobs", String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode responseJson = objectMapper.readTree(response.getBody());

        assertThat(responseJson.isMissingNode()).isFalse();
        assertThat(responseJson.toString()).isEqualTo("[]");
    }




    @Test
    public void addSchedulerJobIntTest() throws  Exception{
        SchedulerJob schedulerJob = new SchedulerJob();
        schedulerJob.setName("ALB Cleanup");
        schedulerJob.setDescription("Cleanup of alb jobs. Please do not deactivate!");
        schedulerJob.setType(SchedulerJobType.REST);
        schedulerJob.setActive(true);
        schedulerJob.setStartMissedRun(false);
        schedulerJob.setCategory("SYSTEM");
        schedulerJob.setCronExpression(null);
        schedulerJob.setScheme("testScheme");
        schedulerJob.setIdRegion(1);
        schedulerJob.setAlbEndpoint("testAlbEndPoint");
        schedulerJob.setAlbPayload("SCHED_ALB");
        schedulerJob.setAlbPrio(1);
        schedulerJob.setAlbJobUser("MKRAUS");
        schedulerJob.setScriptParams("testScriptParams");
        schedulerJob.setShellScriptParams("clear_tmp 15");
        schedulerJob.setSoapEndpointAlias("");
        schedulerJob.setSoapImportPath("CORE/CORE2003/imp/price");
        schedulerJob.setSoapExportPath("testExportPath");
        schedulerJob.setSoapPayload("<api:readPartnersByIdRequest>");
        schedulerJob.setSoapAction("urn:readPartnersById");
        schedulerJob.setRestEndpointAlias("testEndpointAlias");
        schedulerJob.setRestUrl("testUrl");
        schedulerJob.setRestEntityContent("");
        schedulerJob.setRestExportPath("testRestExportPath");
        schedulerJob.setHookScriptName("testHookScriptName");
        schedulerJob.setMinutes("");
        schedulerJob.setHours("");






        String plainCredentials="gasx:gasx!";
        String base64Credentials = Base64.getEncoder().encodeToString(plainCredentials.getBytes());
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Basic " + base64Credentials);
        headers.add("Accept" , "application/json");


        HttpEntity<String> entity = new HttpEntity<String>(asJsonString(schedulerJob), headers);


        //    ResponseEntity<Void> response = testRestTemplate.postForEntity("http://localhost:"+port +"/gasx/restscd/addschedulerjob", entity,Void.class);
        ResponseEntity<Void> response = testRestTemplate.postForEntity("http://localhost:" + port +"/gasx/restscd/addschedulerjob", asJsonString(schedulerJob),Void.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);

    }

    private String createURLWithPort(String uri) {
        return "http://localhost:" + port + uri;
    }

    @Test
    public void updateSchedulerJobTest(){
        SchedulerJob schedulerJob = new SchedulerJob();
        schedulerJob.setName("ALB Cleanup");
        schedulerJob.setDescription("Cleanup of alb jobs. Please do not deactivate!");
        schedulerJob.setType(SchedulerJobType.REST);
        schedulerJob.setActive(true);
        schedulerJob.setStartMissedRun(false);
        schedulerJob.setCategory("SYSTEM");
        schedulerJob.setCronExpression(null);
        schedulerJob.setScheme("testScheme");
        schedulerJob.setIdRegion(1);
        schedulerJob.setAlbEndpoint("testAlbEndPoint");
        schedulerJob.setAlbPayload("SCHED_ALB");
        schedulerJob.setAlbPrio(1);
        schedulerJob.setAlbJobUser("MKRAUS");
        schedulerJob.setScriptParams("testScriptParams");
        schedulerJob.setShellScriptParams("clear_tmp 15");
        schedulerJob.setSoapEndpointAlias("");
        schedulerJob.setSoapImportPath("CORE/CORE2003/imp/price");
        schedulerJob.setSoapExportPath("testExportPath");
        schedulerJob.setSoapPayload("<api:readPartnersByIdRequest>");
        schedulerJob.setSoapAction("urn:readPartnersById");
        schedulerJob.setRestEndpointAlias("testEndpointAlias");
        schedulerJob.setRestUrl("testUrl");
        schedulerJob.setRestEntityContent("");
        schedulerJob.setRestExportPath("testRestExportPath");
        schedulerJob.setHookScriptName("testHookScriptName");
        schedulerJob.setMinutes("");
        schedulerJob.setHours("");

        ResponseEntity<Void> response = testRestTemplate.withBasicAuth("gasx" ,"gasx!").postForEntity("http://localhost:" + port +"/gasx/restscd/updateschedulerjob", schedulerJob,Void.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);

    }

    @Test
    public void deleteSchedulerJob(){

        SchedulerJob schedulerJob = new SchedulerJob();
        schedulerJob.setName("ALB Cleanup");
        schedulerJob.setDescription("Cleanup of alb jobs. Please do not deactivate!");
        schedulerJob.setType(SchedulerJobType.REST);
        schedulerJob.setActive(true);
        schedulerJob.setStartMissedRun(false);
        schedulerJob.setCategory("SYSTEM");
        schedulerJob.setCronExpression(null);
        schedulerJob.setScheme("testScheme");
        schedulerJob.setIdRegion(1);
        schedulerJob.setAlbEndpoint("testAlbEndPoint");
        schedulerJob.setAlbPayload("SCHED_ALB");
        schedulerJob.setAlbPrio(1);
        schedulerJob.setAlbJobUser("MKRAUS");
        schedulerJob.setScriptParams("testScriptParams");
        schedulerJob.setShellScriptParams("clear_tmp 15");
        schedulerJob.setSoapEndpointAlias("");
        schedulerJob.setSoapImportPath("CORE/CORE2003/imp/price");
        schedulerJob.setSoapExportPath("testExportPath");
        schedulerJob.setSoapPayload("<api:readPartnersByIdRequest>");
        schedulerJob.setSoapAction("urn:readPartnersById");
        schedulerJob.setRestEndpointAlias("testEndpointAlias");
        schedulerJob.setRestUrl("testUrl");
        schedulerJob.setRestEntityContent("");
        schedulerJob.setRestExportPath("testRestExportPath");
        schedulerJob.setHookScriptName("testHookScriptName");
        schedulerJob.setMinutes("");
        schedulerJob.setHours("");

        ResponseEntity<Void> response = testRestTemplate.withBasicAuth("gasx" ,"gasx!").postForEntity("http://localhost:" + port +"/gasx/restscd/deleteschedulerjob", schedulerJob,Void.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);


    }


    public static String asJsonString(final Object obj) {
        try {
            return new ObjectMapper().writeValueAsString(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

My problems:

1.)Wheneever I put breakpoint in Rest Controller, it doesnt' stop there, actually it is not getting invoked.

2.)When I run the test for GET it returns sign-in html page from response.getBody()

3.)When I run the test for POST it returns status 401 unauthorized

tried numerious possible solutions on google even disabled spring security by commenting the the configuration still it doesn't work.

I can call the same Rest Controller from my Unit test and can stop the breakpoints.

My security configurations:-

package com.gasx.corex.scheduler.server;

import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;

import com.gasx.corex.ext.user.domain.DefaultRoles;

@Configuration
@EnableWebSecurity
@Order(1)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        // @formatter:off
        httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .httpBasic().and()
            .authorizeRequests()
                .antMatchers("/gasx/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName(), DefaultRoles.ACTUATOR.getName())
                .antMatchers("/webjars/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName(), DefaultRoles.ACTUATOR.getName())
                .antMatchers("/monitor/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ACTUATOR.getName())
                // dev urls
                .antMatchers("/h2-console/**").hasAuthority(DefaultRoles.ROOT.getName())
                .antMatchers("/swagger*/**","/v2/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName())
                .anyRequest().denyAll();
        // @formatter:on

        httpSecurity.csrf().disable();
        httpSecurity.headers().frameOptions().disable();
    }
}

Tried one more thing, added below class to my package :-

package com.gasx.corex.ext.scheduler.integrationtest.domain;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class AllowAnonymousWebAccess extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity web) throws Exception {
        web.antMatcher("**/*").anonymous();
    }
}

and now it gives 404.

I don't know anything about this project's SecurityConfiguration (you should provide some more information about it), but I think that you should provide some authorization data (Like a JWT in the Authorization header, or so)

Could you give me some more information about the SecurityConfig? (look for org.springframework.security.config.something.something... imports )

EDIT

I took a look at your code, and actually this part

    httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
        .httpBasic().and()
        .authorizeRequests()
            .antMatchers("/gasx/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName(), DefaultRoles.ACTUATOR.getName())

is protecting your API with an httpBasic type authorization. You shold provide the credentials in the header to test your application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM