Initialising MockMvc through Mockito - spring

I'm having some trouble trying to get MockMvc to run with Mockito. This is what I have so far:
public class mockito {
MockMvc mockMvc;
#InjectMocks
EntryController controller;
#Mock
DAO data_access_object;
SmokeEvent evt = new SmokeEvent(18);
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = standaloneSetup(controller).setMessageConverters(new MappingJackson2HttpMessageConverter()).build();
//Exception thrown at above line (line 44) when the build method is called
}
#Test
public void viewRendersCorrectly() throws Exception
{
/**
* This test method is supposed to check to see if the controller renders
* correctly
*/
when(data_access_object.getEvent(any(Integer.class))).thenReturn(evt);
}
}
The following is the stack trace it throws in Testing mode. I should also state that I've been working through the Spring REST tutorial over at spring.io
java.lang.ExceptionInInitializerError: null
at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:1499)
at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1322)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:721)
at javax.servlet.GenericServlet.<clinit>(GenericServlet.java:95)
at org.springframework.test.web.servlet.MockMvcBuilderSupport.createMockMvc(MockMvcBuilderSupport.java:50)
at org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder.build(DefaultMockMvcBuilder.java:193)
at test.mockito.setup(mockito.java:44)
Any help is appreciated.
Thanks

Since you are running a standalone test, you need to create an instance of EntryController for standaloneSetup() method. As it is, you're passing standaloneSetup a null reference.
The other option is to run a semi-integrated test with MockMvcBuilders.webAppContextSetup and an appropriate WebApplicationContext.
for example:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(classes= {yourconfigurationClasses.class})
public class ... {
#Inject
protected WebApplicationContext webApplicationContext;
#Before
public void beforeSetUp() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

Related

Spring MockMVC Test weird behaviour. single vs "all" execution

I am currently experiencing a weird issue regarding Spring's MockMvc in combination with Spring Security in JUnit Tests.
When I run a whole class of tests, everything works fine and the tests are passing.
But when I run All Tests in the Project one test is always failing in that certain class and it doesn't matter if I remove the test method failing, then another one fails in the same class.
#SpringBootTest
#ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
class AuthenticationApiTest {
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
private static ObjectMapper objectMapper;
#BeforeAll
static void beforeAll() {
objectMapper = new ObjectMapper();
}
#BeforeEach
void setUp(RestDocumentationContextProvider documentation) {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext)
.apply(documentationConfiguration(documentation)
.operationPreprocessors()
.withRequestDefaults(prettyPrint(),removeHeaders("Content-Length","Host","Pragma","X-XSS-Protection","Expires","X-Frame-Options","X-Content-Type-Options","Cache-Control"))
.withResponseDefaults(prettyPrint(),removeHeaders("Content-Length","Host","Pragma","X-XSS-Protection","Expires","X-Frame-Options","X-Content-Type-Options","Cache-Control")))
.apply(springSecurity())
.build();
}
The test which fails:
#Test
public void testSignUpFail() throws Exception {
SignUpBody signUpBody = new SignUpBody();
signUpBody.setPassword("demo1234");
signUpBody.setFirstname("first");
signUpBody.setLastname("lastn");
this.mockMvc.perform(post("/auth/user/signup")
.header(HttpHeaders.CONTENT_TYPE,"application/json")
.content(objectMapper.writeValueAsString(signUpBody))
).andExpect(status().is(400))
.andDo(document("user-signup-fail"));
this.mockMvc.perform(post("/auth/vendor/signup")
.header(HttpHeaders.CONTENT_TYPE,"application/json")
.content(objectMapper.writeValueAsString(signUpBody))
).andExpect(status().is(400))
.andDo(document("vendor-signup-fail"));
}
Any suggestions on how to solve this weird issue?

Async RestController endpoints :: Async result for handler was not set during the specified timeToWait=0

We have endpoints of the form:
#GetMapping("/myurl")
public Callable<String> getARandomString(#RequestParam int a) {
The application is configured with just one thread (that's why we use Callables to handle this). However, in order to create the tests for this, we do the setup as follows:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {MyApplication.class, MyController.class})
#ActiveProfiles("test")
public class MyControllerTest {
#MockBean
private MyService myService;
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void before() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.build();
when(myServices.isOk()).thenReturn(true);
}
#Test
public void given_when_then() throws Exception {
MvcResult mvcResult = mockMvc.perform(get("/myurl")
.param("a", 1))
.andExpect(request().asyncStarted())
.andReturn();
mvcResult.getAsyncResult();
mockMvc
.perform(asyncDispatch(mvcResult))
.andExpect(status().isOk());
}
1 test at the time works perfect. On the contrary, when having more than 1 test an exception as the following is thrown:
java.lang.IllegalStateException: Async result for handler [public java.util.concurrent.Callable<String> com.antmordel.MyController. getARandomString(int)] was not set during the specified timeToWait=0
I reckon that it is something about the timeouts. Have anybody had this issue?
I had the exactly same problem. 01 test = OK, multiple tests in 01 run = FAIL.
Fixed by telling the TestRunner to consider that the current test makes the context "dirty".
Add
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) to your test class
See this question Reload Spring application context after every test

CrudRepository test cases without inserting data in DB

I have one repository class which which implements CrudRepository. Then in service class I have auto wired this repositary. Then in controller class I have autowired this service.
I want to write test cases of controller Class. I am using below configuration.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class XYZControllerTest {
MockMvc mockMvc;
#Mock
private XYZController xyzController;
#Autowired
private TestRestTemplate template;
#Autowired
XYZRepository xyzRepository;
#Before
public void setup() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(xyzController).build();
}
#Test
public void testPanelShouldBeRegistered() throws Exception {
HttpEntity<Object> xyz = getHttpEntity("{\"name\": \"test 1\", \"email\": \"test10000000000001#gmail.com\","
+ " \"registrationNumber\": \"41DCT\",\"registrationDate\":\"2018-08-08T12:12:12\" }");
ResponseEntity<XYZ> response = template.postForEntity("/api/xyz", xyz, XYZ.class);
}
}
My problem is that when I run test case, data is going to insert in DB which is used for application. Can I test it without inserting data in DB.
Conceptually when we are testing services we mock repositories instead of injection.
You need to mock your repository and setup behavior for returning data.
An example :
#MockBean
XYZRepository xyzRepository;
#Test
public void test() {
// other mocks
//
when(xyzRepository.findAll()).thenReturn(Arrays.asList(new XYZ()));
// service calls
// assertions
}

Spring boot test - PowerMockito to mock and stub constructor

Using Spring boot starter test for testing my application but I am using third party library. Lets suppose we have a class TRequest and it has some constructor and I want to mock and stub that constructor to return the result.
#SpringBootTest
#RunWith(SpringRunner.class)
#PrepareForEverythingForTest
public class TestClass {
#MockBean
TRequest trequest ;
#Before
public void setUp() throws Exception {
PowerMockito.whenNew(TRequest.class).withAnyArguments().thenReturn(trequest);
}
}
Now when I am trying to create the constructor using new, it is not returning the correct stubbed result.
TRequest trequest1 = new TRequest("apiKey","secretKey") ;
trequest.equals(trequest1) ; // false but I want it to be true
Have used a jackson third party lib to test with. - getting ClassLoader exceptions because of PowerMock though.
#SpringBootTest
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringRunner.class)
public class TestPowerMockito {
#MockBean
ObjectMapper object;
#Before
public void init() throws Exception {
PowerMockito.whenNew(ObjectMapper.class).withAnyArguments().thenReturn(object);
}
#Test
public void test() {
assertEquals(object, new ObjectMapper());
}
}

How to mock autowired dependencies in Spring Boot MockMvc Unit tests?

I am expanding upon the basic Spring Boot examples, adding an "autowired" repository dependency to my controller. I would like to modify the unit tests to inject a Mockito mock for that dependency, but I am not sure how.
I was expecting that I could do something like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MockServletContext.class)
#WebAppConfiguration
public class ExampleControllerTest {
private MockMvc mvc;
#InjectMocks
ExampleController exampleController;
#Mock
ExampleRepository mockExampleRepository;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(new ExampleController()).build();
}
#Test
public void getExamples_initially_shouldReturnEmptyList() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/example").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("[]")));
}
}
but it doesn't inject the mock into the MockMvc. Can anyone explain how to do this with #Autowired dependencies, rather than constructor arguments?
Please use #RunWith(MockitoJUnitRunner.class) instead of #RunWith(SpringJUnit4ClassRunner.class)
and you have to use the ExampleController exampleController; field with the injected mocks instead of creating a new one in line mvc = MockMvcBuilders.standaloneSetup(new ExampleController()).build();

Resources