java.lang.IllegalStateException: Failed to load ApplicationContext While running gradle clean build - java

I have 2 Test files but whenever I try to run gradle clean build,
I getting java.lang.IllegalStateException: Failed to load ApplicationContext, when i remove the #AutoConfigureMockMvc, then i get an error Could not autowire. No beans of 'MockMvc' type found.
1st File JobTest
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class JobTest {
#Autowired
private WebApplicationContext applicationContext;
#Autowired
private MockMvc mockMvc;
#MockBean
private JobService jobService;
private static final String URI = "/testJob/";
#BeforeEach
void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(applicationContext).build();
}
private final UUID jobId = UUID.fromString("d35089c0-8ca8-4a9d-8932-8464e9a0736c");
#Test
public void testRequestJob() throws Exception {
//create a request object
RequestBuilder requestBuilder = MockMvcRequestBuilders.post(URI)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.ALL)
.content("testRequestString");
when(jobService.neededJob(anyString()).thenReturn(mockJob);
ResultActions perform = mockMvc.perform(requestBuilder);
assertEquals(HttpStatus.OK.value(), perform.andReturn().getResponse().getStatus());
//perform the request and get the response
perform.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.data.jobId").exists());
}
}
2nd File EmployerTest
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class ShiftControllerTest {
#Autowired
private WebApplicationContext applicationContext;
#Autowired
private MockMvc mockMvc;
#MockBean
private EmployerService employerService;
#BeforeEach
void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(applicationContext).build();
}
private final UUID jobId = UUID.fromString("d35089c0-8ca8-4a9d-8932-8464e9a0736c");
private static final String URI = "/employer/";
#Test
public void testEmployer() throws Exception {
RequestBuilder requestBuilder = MockMvcRequestBuilders.get(URI + jobId)
.accept(MediaType.ALL);
when(employerService.getEmployer(jobId)).thenReturn(mockEmployer);
ResultActions perform = mockMvc.perform(requestBuilder);
assertEquals(HttpStatus.OK.value(), perform.andReturn().getResponse().getStatus());
}
}
If I comment one file and then try to run gradle clean build it works properly, any suggestion will be appreciated.

In the code that you have posted you don't seem to use the WebApplicationContext for anything else apart from creating a MockMvc object which you have already created anyway by virtue of the #Autowired annotation. If you don't need it for anything else try just removing the WebApplicationContext. For example:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class JobTest {
// #Autowired
// private WebApplicationContext applicationContext;
#Autowired
private MockMvc mockMvc;
#MockBean
private JobService jobService;
private static final String URI = "/testJob/";
// #BeforeEach
// void setup() {
// this.mockMvc = MockMvcBuilders.webAppContextSetup(applicationContext).build();
// }
private final UUID jobId = UUID.fromString("d35089c0-8ca8-4a9d-8932-8464e9a0736c");
#Test
public void testRequestJob() throws Exception {
//create a request object
RequestBuilder requestBuilder = MockMvcRequestBuilders.post(URI)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.ALL)
.content("testRequestString");
when(jobService.neededJob(anyString()).thenReturn(mockJob);
ResultActions perform = mockMvc.perform(requestBuilder);
assertEquals(HttpStatus.OK.value(), perform.andReturn().getResponse().getStatus());
//perform the request and get the response
perform.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.data.jobId").exists());
}
}

Related

MockMvc Spring Boot springSecuirtyChainCannotBeNull issue

Can someone point me to what could be wrong in below code. It is a boot spring 2.6.7 application. When test profile is running, it throws error for all tests like below.
java.lang.IllegalStateException: springSecurityFilterChain cannot be null. Ensure a Bean with the name springSecurityFilterChain implementing Filter is present or inject the Filter to be used
#AutoConfigureMockMvc
#SpringBootTest(classes = some.class)
#ActiveProfiles("test")
public class someTest {
#Autowired
private MockMvc mvc;
#Autowired
private WebApplicationContext webAppContext;
#MockBean
private SomeBean someBean;
#SpyBean
private SomeSpyBean someSpyBean;
#BeforeEach
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(webAppContext)
.apply(springSecurity())
.build();
}
#Test
public void SomeTest1() throws Exception {
String text = "text1";
when(someBean.findStuff(text).thenReturn(Optional.of(new Thingie()));
mvc.perform(multipart("/api/somepath/")
.andExpect(status().isNotFound());
verify(someSpyBean).doStuff();
}
#Test
public void SomeTest2() throws Exception {
String text = "text2";
when(someBean.findStuff(text).thenReturn(Optional.of(new Thingie()));
mvc.perform(multipart("/api/somepath/")
.andExpect(status().isFound());
verify(someSpyBean).doStuff();
}
}

Integration test for RESTful Web Service

This is my integration test controller class. Method get all team and there was a problem with compilation:
#SpringJUnitWebConfig(classes = CrewApplication.class)
public class Team_Controller_Integration_Test {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setup() throws Exception
{
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
MockitoAnnotations.initMocks(this);
}
#Test
void getAccount() throws Exception {
this.mockMvc.perform(get("/teams")
.accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json;charset=UTF-8"))
.andExpect(jsonPath("$version").value(null))
.andExpect(jsonPath("$name").value("Apacze"))
.andExpect(jsonPath("$createOn").value(null))
.andExpect(jsonPath("modifiedOn").value(null))
.andExpect(jsonPath("$description").value("grupa programistow"))
.andExpect(jsonPath("$city").value("Włocławek"))
.andExpect(jsonPath("$headcount").value(null));
}
}
This is my error:
java.lang.NullPointerException
On the other hand I create test for Db adn I have problem becouse after add mock elements to db they return null:
#RunWith(SpringRunner.class)
#DataJpaTest
public class Team_database_integration_test {
#MockBean
private TeamRepository teamRepository;
#Autowired
private TestEntityManager testEntityManager;
#Test
public void testDb(){
Team team = new Team(1L,"teamName","teamDescription","krakow",7);
testEntityManager.persist(team);
testEntityManager.flush();
System.out.println(team);
}
}
Add this dependency declaration to test case
#Autowired
private WebApplicationContext webApplicationContext;
and correct the initialization
#Before
public void setup() throws Exception
{
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
MockitoAnnotations.initMocks(this);
}
try changing to this signature,i think content type is by default -json.Try without assertions first then add assertions for validations!
MvcResult CDTO = this.mockMvc.perform(get("/plan/1"))
.andExpect(status().isOk())
.andReturn();

#SpringBootTest causes #PostConstruct to be called twice

With Spring Boot of version 1.4 sone test annotations where deprecated "in favor of {#link SpringBootTest}".
Hovewer simply replacing deprecated annotations with new one, causes one strange side affect for me, #PostConstruct is called twice.
So lets assume that it was before
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {ApplicationTestContext.class})
#IntegrationTest
#Transactional
public class EmployeesControllerSpringTest {
#Inject
private EmployeeRepository employeeRepository;
#Inject
private VenueRepository venueRepository;
#Inject
private TestUtilDummyObjects dummyObjects;
#Inject
private MappingJackson2HttpMessageConverter jacksonMessageConverter;
#Inject
private EntityManager entityManager;
#Inject
private ExceptionTranslator exceptionTranslator;
private MockMvc mockMvc;
#PostConstruct
public void postConstruct() {
EmployeesController sut = new EmployeesController(employeeRepository);
mockMvc = MockMvcBuilders
.standaloneSetup(sut)
.setControllerAdvice(exceptionTranslator)
.setMessageConverters(jacksonMessageConverter)
.build();
}
So, replasing deprecated annottions with the following
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {ApplicationTestContext.class})
#Transactional
causes #PostConstruct to be called twice.
Maybe someone can suggest, what am I doing wrong?
Please see ApplicationTestContext.class below:
//#TestConfiguration
//#SpringBootConfiguration
#ComponentScan(excludeFilters = {#ComponentScan.Filter(type = FilterType.REGEX,
pattern = "somepath.*")})
#EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class})
#EnableConfigurationProperties({ApplicationProperties.class, LiquibaseProperties.class})
#EnableAspectJAutoProxy(proxyTargetClass = false)
public class ApplicationTestContext extends WebMvcConfigurerAdapter {
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new LocalDateConverter(Constants.DATE_FORMAT));
registry.addConverter(new LocalDateTimeConverter(Constants.DATE_TIME_FORMAT));
}
}
UPDATE
Following #bhantol sugestion (get rid of all redundand annotations), I've tried to run official sample https://spring.io/guides/gs/spring-boot/.
Simply downloading sources and changing #Before to #PostConstruct still causing it to be called twice.
code from the sample is below:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {
#LocalServerPort
private int port;
private URL base;
#Autowired
private TestRestTemplate template;
//#Before
#PostConstruct
public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/");
System.out.println("");
}
#Test
public void getHello() throws Exception {
ResponseEntity<String> response = template.getForEntity(base.toString(),
String.class);
assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
}
}
Not sure, but seems like a potential bug.

Mockito - Mock autowired repository in service

I'm triying to write a test from a controller.
The controller call a service who call an autowired repository.
Here is my class right now
#RunWith(MockitoJUnitRunner.class)
public class AdminDestinationControllerTest {
private final PTUser user = new PTUser();
private MockMvc mockMvc;
#InjectMocks
private AdminDestinationController adminDestinationController;
#Mock private RoutingDestinationServiceImpl routingDestinationService;
#Mock private PTRoutingDestinationRepository destinationRepository;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(adminDestinationController).build();
}
#Test
public void setCost_UnknownCode() throws Exception {
when(routingDestinationService.setCost(Mockito.anyString(), Mockito.any())).thenCallRealMethod();
when(destinationRepository.setCost(Mockito.anyString(), Mockito.any())).thenReturn(Optional.empty());
mockMvc.perform(post("/admin/destinations/cost").content("{\"code\":\"99999\", \"cost\":\"2\"}").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNotFound());
}
}
But in the service, the repository is null.
Any ideas of how I could do ?
Thank you

Inject mock into Spring MockMvc WebApplicationContext

I'm working to test (via JUnit4 and Spring MockMvc) a REST service adapter using Spring-boot. The adapter simply passes along requests made to it, to another REST service (using a custom RestTemplate) and appends additional data to the responses.
I'd like to run MockMvc tests to perform controller integration tests, but want to override the RestTemplate in the controller with a mock to allow me to predefine the 3rd party REST response and prevent it from being hit during each test. I've been able to accomplish this by instantiating a MockMvcBuilders.standAloneSetup() and passing it the controller to be tested with the mock injected as listed in this post (and my setup below), however I am not able to do the same using MockMvcBuilders.webAppContextSetup().
I've been through a few other posts, none of which answer the question as to how this might be accomplished. I would like to use the actual Spring application context for the tests instead of a standalone to prevent any gaps as the application is likely to grow.
EDIT: I am using Mockito as my mocking framework and am trying to inject one of its mocks into the context. If this isn't necessary, all the better.
Controller:
#RestController
#RequestMapping(Constants.REQUEST_MAPPING_PATH)
public class Controller{
#Autowired
private DataProvider dp;
#Autowired
private RestTemplate template;
#RequestMapping(value = Constants.REQUEST_MAPPING_RESOURCE, method = RequestMethod.GET)
public Response getResponse(
#RequestParam(required = true) String data,
#RequestParam(required = false, defaultValue = "80") String minScore
) throws Exception {
Response resp = new Response();
// Set the request params from the client request
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(Constants.PARAM_DATA, data);
parameters.put(Constants.PARAM_FORMAT, Constants.PARAMS_FORMAT.JSON);
resp = template.getForObject(Constants.RESTDATAPROVIDER_URL, Response.class, parameters);
if(resp.getError() == null){
resp.filterScoreLessThan(new BigDecimal(minScore));
new DataHandler(dp).populateData(resp.getData());
}
return resp;
}
}
Test class:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#SpringApplicationConfiguration(classes = MainSpringBootAdapter.class)
#TestPropertySource("/application-junit.properties")
public class WacControllerTest {
private static String controllerURL = Constants.REQUEST_MAPPING_PATH + Constants.REQUEST_MAPPING_RESOURCE + compressedParams_all;
private static String compressedParams_all = "?data={data}&minScore={minScore}";
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#InjectMocks
private Controller Controller;
#Mock
private RestTemplate rt;
#Value("${file}")
private String file;
#Spy
private DataProvider dp;
#Before
public void setup() throws Exception {
dp = new DataProvider(file);
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Test
public void testGetResponse() throws Exception {
String[] strings = {"requestData", "100"};
Mockito.when(
rt.getForObject(Mockito.<String> any(), Mockito.<Class<Object>> any(), Mockito.<Map<String, ?>> any()))
.thenReturn(populateTestResponse());
mockMvc.perform(get(controllerURL, strings)
.accept(Constants.APPLICATION_JSON_UTF8))
.andDo(MockMvcResultHandlers.print());
Mockito.verify(rt, Mockito.times(1)).getForObject(Mockito.<String> any(), Mockito.<Class<?>> any(), Mockito.<Map<String, ?>> any());
}
private Response populateTestResponse() {
Response resp = new Response();
resp.setScore(new BigDecimal(100));
resp.setData("Some Data");
return resp;
}
}
Spring's MockRestServiceServer is exactly what you're looking for.
Short description from javadoc of the class:
Main entry point for client-side REST testing. Used for tests that involve direct or indirect (through client code) use of the RestTemplate. Provides a way to set up fine-grained expectations on the requests that will be performed through the RestTemplate and a way to define the responses to send back removing the need for an actual running server.
Try to set up your test like this:
#WebAppConfiguration
#ContextConfiguration(classes = {YourSpringConfig.class})
#RunWith(SpringJUnit4ClassRunner.class)
public class ExampleResourceTest {
private MockMvc mockMvc;
private MockRestServiceServer mockRestServiceServer;
#Autowired
private WebApplicationContext wac;
#Autowired
private RestOperations restOperations;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
mockRestServiceServer = MockRestServiceServer.createServer((RestTemplate) restOperations);
}
#Test
public void testMyApiCall() throws Exception {
// Following line verifies that our code behind /api/my/endpoint made a REST PUT
// with expected parameters to remote service successfully
expectRestCallSuccess();
this.mockMvc.perform(MockMvcRequestBuilders.get("/api/my/endpoint"))
.andExpect(status().isOk());
}
private void expectRestCallSuccess() {
mockRestServiceServer.expect(
requestTo("http://remote.rest.service/api/resource"))
.andExpect(method(PUT))
.andRespond(withSuccess("{\"message\": \"hello\"}", APPLICATION_JSON));
}
}
Here's another solution. Simply put, it just creates a new RestTemplate bean and overrides the one already registered.
So while it performs produces the same functionality as #mzc answer, it allows me to use Mockito to craft the response and verification matchers a bit easier.
Not that it's more than a couple lines of code, but it also prevents from having to add additional code to convert from the Response object to a string for the above mockRestServiceServer.expect().andRespond(<String>) method's arg.
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#SpringApplicationConfiguration(classes = MainSpringBootAdapter.class)
#TestPropertySource("/application-junit.properties")
public class WacControllerTest {
private static String Controller_URL = Constants.REQUEST_MAPPING_PATH + Constants.REQUEST_MAPPING_RESOURCE + compressedParams_all;
#Configuration
static class Config {
#Bean
#Primary
public RestTemplate restTemplateMock() {
return Mockito.mock(RestTemplate.class);
}
}
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#InjectMocks
private Controller Controller;
#Mock
private RestTemplate rt;
#Value("${file}")
private String file;
#Spy
private DataProvider dp;
#Before
public void setup() throws Exception {
dp = new DataProvider(file);
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
this.rt = (RestTemplate) this.wac.getBean("restTemplateMock");
}
#Test
public void testGetResponse() throws Exception {
String[] strings = {"request", "100"};
//Set the request params from the client request
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(Constants.PARAM_SINGLELINE, strings[0]);
parameters.put(Constants.PARAM_FORMAT, Constants.PARAMS_FORMAT.JSON);
Mockito.when(
rt.getForObject(Mockito.<String> any(), Mockito.<Class<Object>> any(), Mockito.<Map<String, ?>> any()))
.thenReturn(populateTestResponse());
mockMvc.perform(get(Controller_URL, strings)
.accept(Constants.APPLICATION_JSON_UTF8))
.andDo(MockMvcResultHandlers.print());
Mockito.verify(rt, Mockito.times(1)).getForObject(Mockito.<String> any(), Mockito.<Class<?>> any(), Mockito.<Map<String, ?>> any());
}
private Response populateTestResponse() {
Response resp = new Response();
resp.setScore(new BigDecimal(100));
resp.setData("Some Data");
return resp;
}
}
org.springframework.boot.test.mock.mockito.MockBean #MockBean helped me out.

Categories