I am Junit testing a controller which uses a JPA repositroy for the database. My H2 in memory database is working correctly, and my GET Request mapping is working as expected. My PUT is getting a 403, while I expect a 200. I've tried a variety of different configurations using AutoConfigureMockMvc with secure false, and also excluding security auto configuration.
Is there something I am missing regarding PUT requests, the security configuration, or need to add configuration around the tokens?
Here is my Junit Test, saveTest works correctly while updateTest returns a 403.
@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc(secure = false)
@Import(SecurityConfig.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class DBcontroltest {
@Autowired
DbRequest dbRequest;
@Autowired
ConnectionRequestRepository connectionRequestRepository;
@Autowired
private MockMvc mockMvc;
private String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
private Date date;
private String dateFormatted = "2019-11-26T14:33:13.175+0000";
{
try {
date = simpleDateFormat.parse("2019-11-26T14:33:13.175+0000");
} catch (ParseException e) {
e.printStackTrace();
}
}
@Test
public void saveTest() throws Exception {
ConnectionRequest connectionRequest = new ConnectionRequest((long) 1, "bleep", "market", "dev", "conn1", "fun", "java", "styff", "hello", "whoop", date, "dldl");
connectionRequestRepository.save(connectionRequest);
String body = "{\"connectionId\":1,\"requestor\":\"bleep\",\"market\":\"market\",\"platform\":\"dev\",\"environment\":\"conn1\",\"connectionName\":\"fun\",\"connectionType\":\"java\",\"databaseId\":\"styff\",\"databasePwd\":\"hello\",\"email\":\"whoop\",\"requestDate\":\"" + dateFormatted + "\",\"jobStatus\":\"dldl\"}\n" +
" ";
mockMvc.perform(get("/api/selectDB/{connectionId}" ,1))
.andExpect(content().json(body))
.andExpect(status().isOk());
}
@Test
public void updateTest() throws Exception {
ConnectionRequest connectionRequest = new ConnectionRequest((long) 1, "bleep", "market", "dev", "conn1", "connname", "java", "db", "hello", "email@aol.com", date, "done");
connectionRequestRepository.save(connectionRequest);
String body3 = "{\"requestor\":\"NEWGUY\"}";
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.put("/api/updateDB/{connectionId}" ,1)
.contentType("application/json")
.content(body3);
System.out.println(connectionRequestRepository.findById((long) 1));
this.mockMvc.perform(builder)
.andExpect(MockMvcResultMatchers.status()
.isOk())
.andDo(MockMvcResultHandlers.print());
System.out.println(connectionRequestRepository.findById((long) 1));
}
}
Here is my controller,
@Data
@RestController
@RequestMapping("/api/")
public class DbRequest {
@Autowired
private ConnectionRequestRepository connectionRequestRepository;
private ConnectionRequest connectionRequest;
@GetMapping("/selectDB/{connectionId}")
public ResponseEntity<ConnectionRequest> getRequestById(@PathVariable("connectionId") Long connectionId) throws Exception {
ConnectionRequest connectionRequest = connectionRequestRepository.findById(connectionId)
.orElseThrow(() -> new Exception("Connection Request " + connectionId + " not found"));
return ResponseEntity.ok().body(connectionRequest);
}
@PutMapping("/updateDB/{connectionId}")
public ResponseEntity<ConnectionRequest> updateConnectionRequest(@PathVariable("connectionId") Long connectionId,
@Valid @RequestBody ConnectionRequest connectionRequestDetails) throws Exception {
long completedDateTime = System.currentTimeMillis();
System.out.println("completeDateTime is " + completedDateTime);
ConnectionRequest connectionRequest = connectionRequestRepository.findById(connectionId)
.orElseThrow(() -> new Exception("Connection Request " + connectionId + " not found"));
System.out.println("value for connectionrequest is " + connectionRequest);
System.out.println("value for connectionrequestdetails is " + connectionRequestDetails);
connectionRequest.setRequestor(connectionRequestDetails.getRequestor());
final ConnectionRequest updatedConnectionRequest = connectionRequestRepository.save(connectionRequest);
return ResponseEntity.ok(updatedConnectionRequest);
}
}
This is the output from running the junit test, with good data. I've tested the application, and it's working as expected, only Junit fails.
MockHttpServletRequest:
HTTP Method = PUT
Request URI = /api/updateDB/1
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8"]
Body = {"requestor":"NEWGUY"}
Session Attrs = {org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken@80b6098}
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 = 403
Error message = Forbidden
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"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :403
<Click to see difference>
Create the below for test profile.
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(jsr250Enabled = true)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("root").password("system").roles("SYSTEM");
}
}
Inside your test class,
public class DBcontroltest {
...
@Test
@WithUserDetails(value = "root")
public void updateTest() throws Exception {
...
}
Please visit this project on github, I have setup spring boot testing using spring-security using spring boot.
Config: https://github.com/reflexdemon/shop/blob/master/src/main/java/org/shop/WebSecurityConfig.java
By using csrf I was able to get this working correctly.
MockHttpServletRequestBuilder builder =
put("/api/updateDB/{connectionId}", 1)
.contentType("application/json")
.content(body3)
.contentType(MediaType.APPLICATION_JSON)
.with(csrf());
System.out.println(connectionRequestRepository.findById((long) 1));
this.mockMvc.perform(builder)
.andExpect(content().json(body))
.andExpect(status().isOk())
.andDo(MockMvcResultHandlers.print());
System.out.println(connectionRequestRepository.findById((long) 1));
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.