#WebMvcTest for SOAP? - spring-boot

Is the Spring Boot annotation #WebMvcTest only intended for sliced RestController tests or should SOAP Endpoints be testable with it too?
When I setup my test and run it, I only get a 404 response as if the endpoint wasn't there so I assume it isn't part of the WebMvc slice.
#RunWith(SpringRunner.class)
#WebMvcTest(value = IdServerPortTypeV10.class)
#Import({SecurityConfig.class, ModelMapperConfig.class, WebServiceConfig.class, ControllerTestBeans.class})
public class AccountEndpointTests {
#Autowired
IdServerPortTypeV10 soapEndpoint;
...
#Before
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.apply(springSecurity())
.build();
}
#Test
#WithMockUser(roles = VALID_ROLE)
public void getAccountTest_Success() throws Exception {
mockMvc.perform(
post("/soap/idserver/1.0")
.accept(MediaType.TEXT_XML_VALUE)
.headers(SoapTestUtility.getHeader(SERVICE.getNamespaceURI(), "getAccount"))
.content(SoapTestUtility.getAccountXml())
).andDo(print())
.andExpect(status().isOk());
}
}
The endpoint is enabled in WebServiceConfig.class in which #EnableWs is set.

#WebMvcTest is, as the name implies, only for Spring MVC related tests.
Spring's SOAP support is from the Spring Web Services project which has its own integration testing support.

Related

Mocking OAuth2 client with WebTestClient for servlet applications results in null httpHandlerBuilder

My Spring Boot application acts as an OAuth2 client by using the spring-boot-starter-oauth2-client dependency.
Now I'd like to write an integration test (#SpringBootTest) to verify the behavior of a REST endpoint secured by OAuth2. The Testing OAuth 2.0 Clients documentation describes that it is possible to use mutateWith(mockOAuth2Client()) to mock a login via OAuth2.
public class UserIT {
#Autowired
private WebTestClient webTestClient;
#Test
void test() {
webTestClient
.mutateWith(mockOAuth2Client("keycloak"))
.get()
.uri("/api/user/1345")
.exchange()
.expectStatus().isOk();
}
}
However, the test fails with the following message:
java.lang.NullPointerException: Cannot invoke "org.springframework.web.server.adapter.WebHttpHandlerBuilder.filters(java.util.function.Consumer)" because "httpHandlerBuilder" is null
at org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers$OAuth2ClientMutator.afterConfigurerAdded(SecurityMockServerConfigurers.java:1113)
at org.springframework.test.web.reactive.server.DefaultWebTestClientBuilder.apply(DefaultWebTestClientBuilder.java:265)
at org.springframework.test.web.reactive.server.DefaultWebTestClient.mutateWith(DefaultWebTestClient.java:167)
As far as I have understood it, this WebTestClient setup is only suitable for "Reactive Applications" whereas my application is a "Servlet Application". Unfortunately, I cannot find the necessary information how to mock this OAuth2 client for a servlet application.
I was able to run your exact #Autowired and #Test code successfully with the following test configuration:
#Configuration
#ComponentScan
public class TestConfig {
#Bean
public WebTestClient webTestClient(ApplicationContext applicationContext) {
return WebTestClient.bindToApplicationContext(applicationContext).build();
}
#Bean
public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange().anyExchange().permitAll();
return http.build();
}
}

mock rest api call during integration test in spring boot

I have a spring boot service that validates each request by calling my auth service. Now I am writing an integration test. How can I mock my request to auth service while testing my own APIs?
#GetMapping("/pending/task")
#Operation(summary = "Get user's pending task", tags = "UserTask", security = {#SecurityRequirement(name = Constants.AUTH_TOKEN_HEADER)})
#PreAuthorize(Constants.PreAuthorize.ROLE)
public List<UserTaskDto> getPendingTasks(#Valid #RequestParam long courseId){
// internal logic
}
SpringBoot filter will read the token from the header and verify that against auth service using rest. I want to mock that call during this api testing.
Test Code
class UserTaskControllerTest extends ApplicationTests {
#Mock
RestTemplate restTemplate;
#Test
void shouldGiveAllUserPendingTask(){
HttpHeaders headers = new HttpHeaders();
headers.add(Constants.AUTH_TOKEN_HEADER, GENERIC_AUTH_TOKEN);
Task task = FactoryClass.createTask();
UserTask userTask = FactoryClass.createUserTask();
CentralAuthInfo centralAuthInfo = FactoryClass.getCentralAuthInfo();
taskRepository.save(task);
userTask.setTask(task);
userTaskRepository.save(userTask);
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(USER_PENDING_TASK_BASE_URL)
.queryParam(COURSE_ID, userTask.getCohortId());
when(restTemplate.exchange(ArgumentMatchers.anyString(), ArgumentMatchers.any(HttpMethod.class), ArgumentMatchers.any(HttpEntity.class), ArgumentMatchers.eq(CentralAuthInfo.class))).thenReturn(new ResponseEntity<>(centralAuthInfo, HttpStatus.OK));
ResponseEntity<UserTaskDto> responseEntity = testRestTemplate.exchange(builder.toUriString(), GET, new HttpEntity<>(headers), UserTaskDto.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(200);
}
Spring offers a #WithMockUser that you can add to your tests. I usually use it with a WebTextClient to test API calls. Here is an example with reactive controller but same applies to non-reactive
#Import(SecurityConfig.class)
#WebFluxTest(MyController.class)
class MyControllerTest {
#Autowired
private WebTestClient webTestClient;
...
#Test
#WithMockUser(username="admin",roles={"USER","ADMIN", "ROLE"})
void testPendingTasks() {
webTestClient
.get()
.uri("/pending/task")
.exchange()
.expectStatus()
.isOk();
}
...
}
Maybe #AutoConfigureMockMvc(addFilters = false) will help to disable security for integration test, like this:
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ExtendWith(SpringExtension.class)
#AutoConfigureMockMvc(addFilters = false)
public class FooTest {
#Autowired
private MockMvc mockMvc;
// some of your tests here ....
}
If it's not what you need you can just create a fake auth service class for test purposes and override the behavior in the way you want.

Testing Spring Data Rest

I want to test a Spring boot 2 respository as rest controller app.
App is working well from browser ( http://localhost:8080/api/v1/ehdata ), but I cannot find an example how can I test it with Spring test environment. Very important, there are no RestControllers and Services, only Repositories annotated like this:
#RepositoryRestResource(path = EhDataRepository.BASE_PATH,
collectionResourceRel = EhDataRepository.BASE_PATH)
public interface EhDataRepository extends
PagingAndSortingRepository<EhData, Long> {
public static final String BASE_PATH="ehdata";
}
I tried with this test, but responses was empty, and status code was 404:
#RunWith(SpringRunner.class)
#SpringBootTest
#WebMvcTest(EhDataRepository.class)
public class RestTest extends AbstractRestTest {
#Autowired MockMvc mvc;
#Test
public void testData() throws Exception {
mvc.perform(get("/api/v1/ehdata")
.accept(MediaTypes.HAL_JSON_VALUE))
.andDo(print())
.andExpect(status().isOk())
.andExpect(header().string(HttpHeaders.CONTENT_TYPE,
MediaTypes.HAL_JSON_VALUE+";charset=UTF-8")
.andReturn();
}
}
thx,
Zamek
You will need to mock the output from the respository like this based on the method you are trying to test:
#MockBean
private ProductRepo repo;
And then
Mockito.when(this.repo.findById("PR-123")
.get())
.thenReturn(this.product);
this.mvc.perform(MockMvcRequestBuilders.get("/products/{id}", "PR-123")
.contentType(MediaType.APPLICATION_JSON_VALUE))
.andReturn();
Also, remove the server-context-path while calling API in perform() method.

Unit Test case for Api Controller

How to write Junit test case for this controller?
#PostMapping(path = "/appformsubmission")
public AppFormChannelResponseObject saveAppForm(
#RequestBody AppFormChannelRequestObject<AppFormDetails> requestObject) throws JsonProcessingException {
logger.info("MwController -saveAppForm ");
if (logger.isDebugEnabled()) {
logger.debug("Entering MwController() method");
logger.debug("requestObject : {}", Utility.toJsonString(requestObject));
}
return appFormService.submitApplicationForm(requestObject);
}
It would be great if I get a sample test case as I am new to Junit. Thanks in advance.
From spring boot docs, by using MockMvc for MVC layer testing
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class AppFormChannelTest{
#Autowired
private MockMvc mvc;
#Test
public void saveAppFormTest() throws Exception {
AppFormChannelRequestObject body=new AppFormChannelRequestObject();
Gson gson = new Gson();
String json = gson.toJson(body);
this.mockmvc.perform(post("/appformsubmission/")
.contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(status().isOk());
}
}
Before diving in with MockMVC would suggest you to write Junit Using TestRestTemplate.
Refer this link
This will give you a easy way to test your controllers.

Getting Exception when Trying to run Spring Boot Web test cases. Excpetions : java.lang.NoClassDefFoundError: AsyncRequestTimeoutException

In Setup method when I am attaching Rest Controller Advice to mock mvc then below exception is thrown
java.lang.NoClassDefFoundError: org/springframework/web/context/request/async/AsyncRequestTimeoutException
#RunWith(MockitoJUnitRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AccountDetailsControllerTest {
#Mock
private AccountDetailService accountDetailService;
private MockMvc mockMvc;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.mockMvc = standaloneSetup(new
AccountDetailsController(accountDetailService))
.setControllerAdvice(new ExceptionControllerAdvice())
.build();
}
}
Thanks all, It was issue with Spring dependency. I was using version of 4.3.1 of spring-web and spring boot 1.5.7 expects 4.3.11.

Resources