Spring Boot integration test ignoring secure=false in AutoConfigureMockMvc annotation, get 401

14,270

Solution 1

Adam.

Since I also recently ran into this problem after updating Spring Boot to 2.1.3.RELEASE and Spring Framework to 5.1.4.RELEASE, which forces to add Spring Web Security and If someone wants to not provide security resolver then they are required to disable security in Test Environment, so I decided to share how I ended up resolving this issue.

I was also scratching head while working up an application and writing Integration Test Cases with @SpringBootTest. Using @WebMvcTest is way less painful than this, tbh.

In my case following worked.

@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)//This annotation was required to run it successfully
@DisplayName("UserControllerTest_SBT - SpringBootTest")
class UserControllerTest_SBT extends BaseTest_SBT {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void getUsersList() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get("/user/listAll")
            .accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andDo(print());

    }

}

@ExtendWith(SpringExtension.class) //This is not mandatory
@SpringBootTest
@AutoConfigureMockMvc(secure = false) // Secure false is required to by pass security for Test Cases
@ContextConfiguration //This is also not mandatory just to remove annoying warning, i added it
public class BaseTest_SBT {

}

What didn't work:

1- @SpringBootTest(properties = {"security.basic.enabled=false"}) <-- This solution is deprecated! More details here

2- \src\test\resources\application.properties** -> security.basic.enabled=false

Hopefully, this will be helpful to someone.

Solution 2

Changing

@AutoConfigureMockMvc(secure = false)

to

@AutoConfigureMockMvc(addFilters=false)

works for me.

Share:
14,270

Related videos on Youtube

Adam
Author by

Adam

My interests include Java, photos, music, financial trading, environmental issues, Open Source projects, networking, operating systems like linux (Debian/Ubuntu) and Macs and hardware. SOreadytohelp

Updated on June 18, 2022

Comments

  • Adam
    Adam about 2 years

    Can't make my @SpringBootTest work. It says authentication is on, which I do not want.

    I've set it up with @AutoConfigureMockMvc(secure = false)

    I submit a mock request with some JSON and my integration test should test the whole stack, taking it through the web layer with SDR to JPA and then into the in-memory database, so I can test for it using JdbcTemplate.

    But the response is 401, requires authentication. Why isn't the @AutoConfigureMockMvc(secure = false) enough? What's missing?

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
            classes = { TestDataSourceConfig.class })
    @EnableAutoConfiguration
    @AutoConfigureMockMvc(secure = false)
    @AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
    @Transactional
    public class SymbolRestTests  {
    
        @Autowired
        private MockMvc mockMvc;
        @Autowired
        private JdbcTemplate jdbcTemplate;
        @Autowired
        private SymbolRepository symbolRepository;
        @PersistenceContext
        private EntityManager entityManager;  
    
        @Test
        public void shouldCreateEntity() throws Exception {
    
            String testTitle = "TEST.CODE.1";
            String testExtra = "Test for SymbolRestTests.java";
            String json = createJsonExample(testTitle, testExtra, true);
            log.debug(String.format("JSON==%s", json));
            MockHttpServletRequestBuilder requestBuilder =
                    post("/symbols").content(json);
            mockMvc.perform(requestBuilder)
                    .andExpect(status().isCreated())
                    .andExpect(header().string("Location",
                            containsString("symbols/")));
            entityManager.flush();
            String sql = "SELECT count(*) FROM symbol WHERE title = ?";
            int count = jdbcTemplate.queryForObject(
                    sql, new Object[]{testTitle}, Integer.class);
            assertThat(count, is(1));
        }
    

    Output logging:

    MockHttpServletRequest:
          HTTP Method = POST
          Request URI = /symbols
           Parameters = {}
              Headers = {}
    
    Handler:
                 Type = null
    
    Async:
        Async started = false
         Async result = null
    
    Resolved Exception:
                 Type = null
    
    ModelAndView:
            View name = null
                 View = null
                Model = null
    
    FlashMap:
           Attributes = null
    
    MockHttpServletResponse:
               Status = 401
        Error message = Full authentication is required to access this resource
              Headers = {X-Content-Type-Options=[nosniff], 
                         X-XSS-Protection=[1; mode=block], 
                         Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], 
                         Pragma=[no-cache], 
                         Expires=[0], 
                         X-Frame-Options=[DENY], 
                         Strict-Transport-Security=[max-age=31536000 ; includeSubDomains], 
                         WWW-Authenticate=[Basic realm="Spring"]}
             Content type = null
                     Body = 
            Forwarded URL = null
           Redirected URL = null
                  Cookies = []
    

    I discovered from Spring Boot Integration Test Results in 401 that I can disable security via properties with this:

    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
        classes = { TestDataSourceConfig.class },
        properties = {
                "security.basic.enabled=false"
        })
    

    but really the @AutoConfigureMockMvc(secure = false) should work, so what's blocking it?

  • Adam
    Adam about 5 years
    Thanks for the answer. In the year since that question, I was forced to give up searching for an answer. I find Spring great for some stuff, but I abandoned spring testing as a framework and just stuck with doing those extras by hand. Didn't take too long and frankly I didn't have the choice. It's almost impossible to work out what the problem is by following the source code due to all the annotations, and there was no real way of reducing it to the bare minimum to get it to work, as a base to build it back up to find where it broke. And that was despite comments from two Pivotal devs :(
  • mfaisalhyder
    mfaisalhyder about 5 years
    Yeah, buddy it sucks. Even for me it was like I had to invest almost 2 full days to sort it out what could be the problem as others mentioned using property with @SpringBootTest can suffice but It was not working. Great to hear you managed to get it done other way. May be this will help other people like us who will run into problems after following outdated tutorials.
  • mfaisalhyder
    mfaisalhyder almost 5 years
    @Tejasjain glad that it was helpful for you :)
  • Dmitriy Popov
    Dmitriy Popov over 3 years
    Looks good, but still does not help. @Configuration class is still called from @SpringBootTest. I am calling the endpoints with `RestTemplate, no mocking.
  • Dmitriy Popov
    Dmitriy Popov over 3 years
    This is working for @WebMvcTest tests, but not for @SpringBootTest tests.

Related