#AutoConfigureRestDocs and #AutoConfigureMockMvc do not configure MockMvc correctly. Even manually configuring them do not seem to help.
I tried configuring the MockMvc and MockMvcRestDocumentationConfigurer also manually, but it did not help.
This is the current setup:
#RunWith(SpringRunner.class)
#SpringBootTest(properties= "spring.main.allow-bean-definition-overriding=true")
#AutoConfigureRestDocs
#AutoConfigureMockMvc
public class LoginLogoutTest {
#Autowired
private MockMvc mockMvc;
#Test
public void adminCanLoginLogout() throws Exception {
mockMvc.perform(formLogin().user(TestConfig.ADMIN_USERNAME).password(TestConfig.PASSWORD))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername(TestConfig.ADMIN_USERNAME))
.andDo(document("login"));
mockMvc.perform(logout())
.andExpect(status().isOk())
.andExpect(unauthenticated())
.andDo(document("logout"));
}
}
I also tried configuring them with something like this:
#RunWith(SpringRunner.class)
#SpringBootTest(properties= "spring.main.allow-bean-definition-overriding=true")
public class LoginLogoutTest {
#Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets");
private MockMvc mockMvc;
#Before
public void setUp(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration(this.restDocumentation))
.build();
}
#Test
public void adminCanLoginLogout() throws Exception {
mockMvc.perform(formLogin().user(TestConfig.ADMIN_USERNAME).password(TestConfig.PASSWORD))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername(TestConfig.ADMIN_USERNAME))
.andDo(document("login"));
mockMvc.perform(logout())
.andExpect(status().isOk())
.andExpect(unauthenticated())
.andDo(document("logout"));
}
}
I am getting the following error:
java.lang.IllegalStateException: REST Docs configuration not found. Did you forget to apply a MockMvcRestDocumentationConfigurer when building the MockMvc instance?
What am I doing wrong? The error message is not very informative.
I want to create JUnit test for Rest api and generate api doc. I want to test this code:
Rest controller
#RestController
#RequestMapping("/transactions")
public class PaymentTransactionsController {
#Autowired
private PaymentTransactionRepository transactionRepository;
#GetMapping("{id}")
public ResponseEntity<?> get(#PathVariable String id) {
return transactionRepository
.findById(Integer.parseInt(id))
.map(mapper::toDTO)
.map(ResponseEntity::ok)
.orElseGet(() -> notFound().build());
}
}
Repository interface
public interface PaymentTransactionRepository extends CrudRepository<PaymentTransactions, Integer>, JpaSpecificationExecutor<PaymentTransactions> {
Optional<PaymentTransactions> findById(Integer id);
}
I tried to implement this JUnit5 test with mockito:
#ExtendWith({ RestDocumentationExtension.class, SpringExtension.class })
#SpringBootTest(classes = PaymentTransactionsController.class)
#WebAppConfiguration
public class PaymentTransactionRepositoryIntegrationTest {
.....
private MockMvc mockMvc;
#MockBean
private PaymentTransactionRepository transactionRepository;
#BeforeEach
void setUp(WebApplicationContext webApplicationContext,
RestDocumentationContextProvider restDocumentation) {
PaymentTransactions obj = new PaymentTransactions(1);
Optional<PaymentTransactions> optional = Optional.of(obj);
PaymentTransactionRepository processor = Mockito.mock(PaymentTransactionRepository.class);
Mockito.when(processor.findById(Integer.parseInt("1"))).thenReturn(optional);
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.apply(documentationConfiguration(restDocumentation))
.alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
.build();
}
#Test
public void testNotNull() {
assertNotNull(target);
}
#Test
public void testFindByIdFound() {
Optional<PaymentTransactions> res = target.findById(Integer.parseInt("1"));
// assertTrue(res.isPresent());
}
#Test
public void indexExample() throws Exception {
this.mockMvc.perform(get("/transactions").param("id", "1"))
.andExpect(status().isOk())
.andExpect(content().contentType("application/xml;charset=UTF-8"))
.andDo(document("index-example", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), links(linkWithRel("crud").description("The CRUD resource")), responseFields(subsectionWithPath("_links").description("Links to other resources")),
responseHeaders(headerWithName("Content-Type").description("The Content-Type of the payload, e.g. `application/hal+json`"))));
}
}
I get error:
java.lang.AssertionError: Status expected:<200> but was:<404>
What his the proper way to to make GET request to the above code?
Probably I need to add response OK when message is send back?
hi in my case i needed #MockBean of controller and all services that is was autowireing ;)
Instead of #PostMapping and #GetMapping which caused same problem while #RequestMapping in controller helped
It's a path variable, so instead of using param value, please use path variable.
For MvcResult import, you can import org.springframework.test.web.servlet
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
...
given(target.findById(anyInt())).willReturn(Optional.of(new PaymentTransactions(1))).andReturn();
MvcResult result = this.mockMvc.perform(get("/transactions/1")
.accept("application/xml;charset=UTF-8")).andReturn();
String content = result.getResponse().getContentAsString();
this.mockMvc.perform(get("/transactions/1")
.accept("application/xml;charset=UTF-8"))
.andExpect(status().isOk())
.andDo(document("index-example", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), links(linkWithRel("crud").description("The CRUD resource")), responseFields(subsectionWithPath("_links").description("Links to other resources")),
responseHeaders(headerWithName("Content-Type").description("The Content-Type of the payload, e.g. `application/hal+json`"))));
Can you try this..
public class PaymentTransactionsControllerTest {
private MockMvc mvc;
#InjectMocks
PaymentTransactionsController paymentTransactionsController;
#MockBean
private PaymentTransactionRepository processor;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(paymentTransactionsController).build();
}
#Test
public void indexExample() throws Exception {
PaymentTransactions obj = new PaymentTransactions(1);
Optional<PaymentTransactions> optional = Optional.of(obj);
Mockito.when(processor.findById(Integer.parseInt("1"))).thenReturn(optional);
MvcResult result = mvc.perform(MockMvcRequestBuilders.get("/transactions/{id}", 1))
.andDo(print())
.andExpect(status().isOk())
.andReturn();
Assert.assertNotNull(result.getResponse().getContentAsString());
}
}
I am creating my first unit test, and just wanted to create something pretty simple based on one of the Spring tutorials.
Here is the error I am getting:
java.lang.AssertionError: Response content
Expected: (null or an empty string)
but: was "Debug"
My Controller:
#RestController
#RequestMapping(value = "/person")
public class PersonController {
#Autowired
protected PersonService personService;
#RequestMapping(value = "/lastName", produces = "application/json")
public String lastName(#RequestParam(value = "cid") String cid)
{
return personService.findByCId(cid).getLastName();
}
My Test:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class MvcLastNameTest {
#Autowired
private MockMvc mockMvc;
#Test
public void shouldReturnNonNullString() throws Exception {
this.mockMvc.perform(get("/person/lastName?cid=123456")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(isEmptyOrNullString()));
}
}
in your test your are expecting EmptyOrNullString, but your controller produces a lastName
change your expectation:
.andExpect(content().string("Debug")); // or any other valid lastName
Trying to test the /health.json endpoint for the actuator for when the status is Up or DOWN.
public class ActuatorTest
{
#TestConfiguration
static class Config
{
#Bean
public HealthIndicator dbHealthIndicator()
{
return Mockito.mock(HealthIndicator.class);
}
}
#Autowired
private MockMvc mvc;
#Autowired
private HealthIndicator dbHealthIndicator;
#Test
public void healthcheck_Up() throws Exception
{
when(dbHealthIndicator.health()).thenReturn(Health.status(Status.UP).build());
mvc.perform(get("/health.json"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.status").value("UP"));
}
#Test
public void healthcheck_Down() throws Exception
{
when(dbHealthIndicator.health()).thenReturn(Health.status(Status.DOWN).build());
mvc.perform(get("/health.json"))
.andExpect(status().isServiceUnavailable())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.status").value("DOWN"));
}
}
the test for when the status is down always gives a status of 200 when infact it should be a 503.
I use Spring MVC and Spring boot to write a Restful service. This code works fine through postman.While when I do the unit test for the controller to accept a post request, the mocked myService will always initialize itself instead of return a mocked value defined by when...thenReturn... I use verify(MyService,times(1)).executeRule(any(MyRule.class)); and it shows the mock is not used.
I also tried to use standaloneSetup for mockMoc, but it complains it can't find the mapping for the path "/api/rule".
Could anybody help to figure out the problem?
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class MyControllerTest {
#Mock
private MyService myService;
#InjectMocks
private MyController myRulesController;
private MockMvc mockMvc;
#Autowired
private WebApplicationContext wac;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void controllerTest() throws Exception{
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
Long userId=(long)12345;
MyRule happyRule = MyRule.createHappyRule(......);
List<myEvent> mockEvents=new ArrayList<myEvent>();
myEvents.add(new MyEvent(......));
when(myService.executeRule(any(MyRule.class))).thenReturn(mockEvents);
String requestBody = ow.writeValueAsString(happyRule);
MvcResult result = mockMvc.perform(post("/api/rule").contentType(MediaType.APPLICATION_JSON)
.content(requestBody))
.andExpect(status().isOk())
.andExpect(
content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
verify(MyService,times(1)).executeRule(any(MyRule.class));
String jsonString = result.getResponse().getContentAsString();
}
}
Below is my controller class, where MyService is a interface. And I have implemented this interface.
#RestController
#RequestMapping("/api/rule")
public class MyController {
#Autowired
private MyService myService;
#RequestMapping(method = RequestMethod.POST,consumes = "application/json",produces = "application/json")
public List<MyEvent> eventsForRule(#RequestBody MyRule myRule) {
return myService.executeRule(myRule);
}
}
Is api your context root of the application? If so remove the context root from the request URI and test. Passing the context root will throw a 404. If you intend to pass the context root then please refer the below test case. Hope this helps.
#RunWith(MockitoJUnitRunner.class)
public class MyControllerTest {
#InjectMocks
private MyController myRulesController;
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = standaloneSetup(myRulesController).build();
}
#Test
public void controllerTest() throws Exception{
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
MyController.User user = new MyController.User("test-user");
ow.writeValueAsString(user);
MvcResult result = mockMvc.perform(post("/api/rule").contentType(MediaType.APPLICATION_JSON).contextPath("/api")
.content(ow.writeValueAsString(user)))
.andExpect(status().isOk())
.andExpect(
content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
}
}
Below is the controller
/**
* Created by schinta6 on 4/26/16.
*/
#RestController
#RequestMapping("/api/rule")
public class MyController {
#RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
public User eventsForRule(#RequestBody User payload) {
return new User("Test-user");
}
public static class User {
private String name;
public User(String name){
this.name = name;
}
}
}