/** * Assert a field error code for a model attribute using a {@link org.hamcrest.Matcher}. * @since 4.1 */ public <T> ResultMatcher attributeHasFieldErrorCode(final String name, final String fieldName, final Matcher<? super String> matcher) { return new ResultMatcher() { @Override public void match(MvcResult mvcResult) throws Exception { ModelAndView mav = getModelAndView(mvcResult); BindingResult result = getBindingResult(mav, name); assertTrue("No errors for attribute: [" + name + "]", result.hasErrors()); boolean hasFieldErrors = result.hasFieldErrors(fieldName); assertTrue("No errors for field: [" + fieldName + "] of attribute [" + name + "]", hasFieldErrors); String code = result.getFieldError(fieldName).getCode(); assertThat("Field name '" + fieldName + "' of attribute '" + name + "'", code, matcher); } }; }
private void assertIncorrectResponseHeaderValue(ResultMatcher resultMatcher, String unexpected) throws Exception { try { this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, oneMinuteAgo))// .andExpect(resultMatcher); fail(EXPECTED_ASSERTION_ERROR_MSG); } catch (AssertionError e) { if (EXPECTED_ASSERTION_ERROR_MSG.equals(e.getMessage())) { throw e; } // [SPR-10659] Ensure that the header name is included in the message // // We don't use assertEquals() since we cannot control the formatting // produced by JUnit or Hamcrest. assertMessageContains(e, "Response header " + LAST_MODIFIED); assertMessageContains(e, unexpected); assertMessageContains(e, now); } }
/** * Assert the given model attribute has error/s * @param attributeName * @return */ public ResultMatcher attributehasGlobalErrors(final String attributeName) { return result -> { ModelAndView mav = getModelAndView(result); BindingResult bindingResult = getBindingResult(mav, attributeName); assertTrue("No global binding errors for attribute: " + attributeName, bindingResult.hasGlobalErrors()); }; }
public ResultMatcher hasGlobalErrorCode(final String attributeName, final String error) { return result -> { ModelAndView mav = getModelAndView(result); BindingResult bindingResult = getBindingResult(mav, attributeName); assertTrue("No global binding errors for attribute: " + attributeName, bindingResult.hasGlobalErrors()); Optional<String> presentError = bindingResult.getGlobalErrors()// .stream()// .map(globalError -> globalError.getCode())// .filter(errorCode -> errorCode.equals(error))// .findAny();// assertTrue("No global error with code " + error + " found for attribute: " + attributeName, presentError.isPresent()); }; }
private ResultMatcher feedbackCreated(FeedbackForm form) { return result -> { List<Feedback> feedbacks = feedbackRepository.findAllOfStudent(student); assertThat(feedbacks, hasSize(1)); Feedback feedback = feedbacks.get(0); assertThat(feedback.getSuggestions(), equalTo(form.getSuggestions())); assertThat(feedback.getType(), equalTo(form.isLike() ? LIKE : DISLIKE)); }; }
private ResultMatcher resultHasUsersPage(Page<UisUser> page) { return result -> { Page actualPage = (Page) result.getModelAndView().getModel().get("page"); assertNotNull(actualPage); assertThat(actualPage.getNumber(), equalTo(page.getNumber())); assertThat(actualPage.getTotalElements(), equalTo(page.getTotalElements())); assertThat(actualPage.getSize(), equalTo(page.getSize())); assertThat(actualPage.getContent(), equalTo(page.getContent())); }; }
private static ResultMatcher orderFieldsAtPath(final Order order, final String jsonPath) throws Exception { return allOf( jsonPath(jsonPath + ".id").value(order.getId()), jsonPath(jsonPath + ".deliveryAddress.firstName").value(order.getDeliveryAddress().getFirstName()), jsonPath(jsonPath + ".deliveryAddress.lastName").value(order.getDeliveryAddress().getLastName()), jsonPath(jsonPath + ".deliveryAddress.street").value(order.getDeliveryAddress().getStreet()), jsonPath(jsonPath + ".deliveryAddress.zip").value(order.getDeliveryAddress().getZip()), jsonPath(jsonPath + ".deliveryAddress.city").value(order.getDeliveryAddress().getCity()), jsonPath(jsonPath + ".deliveryPrice").value(order.calculateDeliveryPrice().getAmount()), orderItemsAtIndex(order.getItems(), jsonPath) ); }
static ResultMatcher orderItemsAtIndex(List<OrderItem> items, String jsonPath) throws Exception { final List<ResultMatcher> matchers = new ArrayList<>(); for (int i = 0; i < items.size(); i++) { matchers.add(orderItemAt(items.get(i), jsonPath + ".items[" + i + "]")); } return allOf(matchers); }
private static ResultMatcher orderItemAt(final OrderItem orderItem, final String jsonPath) throws Exception { return allOf( jsonPath(jsonPath + ".name").value(orderItem.getName()), jsonPath(jsonPath + ".description").value(orderItem.getDescription()), jsonPath(jsonPath + ".weight").value(orderItem.getWeight().getValue()), jsonPath(jsonPath + ".price").value(orderItem.getPrice().getAmount()), jsonPath(jsonPath + ".quantity").value(orderItem.getQuantity()) ); }
private static ResultMatcher allOf(final ResultMatcher... matchers) throws Exception { return (result) -> { for (ResultMatcher m : matchers) { m.match(result); } }; }
private static ResultMatcher allOf(final Iterable<ResultMatcher> matchers) throws Exception { return (result) -> { for (ResultMatcher m : matchers) { m.match(result); } }; }
/** * Tests if the response contains the JSON representation of a paging result with items of the * given type. * * @param clazz the class of the expected paged objects. * @param <T> the type of the expected paged objects. * @return ResultMatcher that performs the test described above. */ public static <T> ResultMatcher containsPagedResources(Class<T> clazz) { return result -> { String json = result.getResponse().getContentAsString(); try { PagedResources<T> pagedResources = JsonHelper.fromPagedResourceJson(json, clazz); assertThat(pagedResources).isNotNull(); } catch (Exception e) { throw new RuntimeException( String.format("expected JSON representation of class %s but found '%s'", clazz, json), e); } }; }
/** * Evaluate the JSON path expression against the response content and * assert that the result is equal to the supplied value. */ public ResultMatcher value(final Object expectedValue) { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { jsonPathHelper.assertValue(result.getResponse().getContentAsString(), expectedValue); } }; }
/** * Evaluate the JSON path expression against the response content and * assert that a value does not exist at the given path. * <p>If the JSON path expression is not {@linkplain JsonPath#isDefinite * definite}, this method asserts that the value at the given path is * <em>empty</em>. */ public ResultMatcher doesNotExist() { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { String content = result.getResponse().getContentAsString(); jsonPathHelper.doesNotExist(content); } }; }
/** * Evaluate the JSON path expression against the response content and * assert that the result is a {@link java.util.Map}. * @since 4.2.1 */ public ResultMatcher isMap() { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { String content = result.getResponse().getContentAsString(); jsonPathHelper.assertValueIsMap(content); } }; }
/** * Assert that the named response header does not exist. * @since 4.0 */ public ResultMatcher doesNotExist(final String name) { return new ResultMatcher() { @Override public void match(MvcResult result) { assertTrue("Response should not contain header " + name, !result.getResponse().containsHeader(name)); } }; }
/** * Assert the primary value of the named response header as a date String, * using the preferred date format described in RFC 7231. * <p>The {@link ResultMatcher} returned by this method throws an {@link AssertionError} * if the response does not contain the specified header, or if the supplied * {@code value} does not match the primary value. * * @see <a href="https://tools.ietf.org/html/rfc7231#section-7.1.1.1">Section 7.1.1.1 of RFC 7231</a> * @since 4.2 */ public ResultMatcher dateValue(final String name, final long value) { return new ResultMatcher() { @Override public void match(MvcResult result) { SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); format.setTimeZone(TimeZone.getTimeZone("GMT")); assertTrue("Response does not contain header " + name, result.getResponse().containsHeader(name)); assertEquals("Response header " + name, format.format(new Date(value)), result.getResponse().getHeader(name)); } }; }
/** * Assert the given model attribute(s) have errors. */ public ResultMatcher attributeErrorCount(final String name, final int expectedCount) { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { ModelAndView mav = getModelAndView(result); Errors errors = getBindingResult(mav, name); assertEquals("Binding/validation error count for attribute [" + name + "], ", expectedCount, errors.getErrorCount()); } }; }
/** * Assert the given model attribute(s) have errors. */ public ResultMatcher attributeHasErrors(final String... names) { return new ResultMatcher() { @Override public void match(MvcResult mvcResult) throws Exception { ModelAndView mav = getModelAndView(mvcResult); for (String name : names) { BindingResult result = getBindingResult(mav, name); assertTrue("No errors for attribute [" + name + "]", result.hasErrors()); } } }; }
/** * Assert the given model attribute field(s) have errors. */ public ResultMatcher attributeHasFieldErrors(final String name, final String... fieldNames) { return new ResultMatcher() { @Override public void match(MvcResult mvcResult) throws Exception { ModelAndView mav = getModelAndView(mvcResult); BindingResult result = getBindingResult(mav, name); assertTrue("No errors for attribute: [" + name + "]", result.hasErrors()); for (final String fieldName : fieldNames) { boolean hasFieldErrors = result.hasFieldErrors(fieldName); assertTrue("No errors for field: [" + fieldName + "] of attribute [" + name + "]", hasFieldErrors); } } }; }
/** * Assert the total number of errors in the model. */ public <T> ResultMatcher errorCount(final int expectedCount) { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { int actualCount = getErrorCount(getModelAndView(result).getModelMap()); assertEquals("Binding/validation error count", expectedCount, actualCount); } }; }
/** * Assert the model has errors. */ public <T> ResultMatcher hasErrors() { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { int count = getErrorCount(getModelAndView(result).getModelMap()); assertTrue("Expected binding/validation errors", count != 0); } }; }
/** * Assert the response body content as a byte array. */ public ResultMatcher bytes(final byte[] expectedContent) { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { assertEquals("Response content", expectedContent, result.getResponse().getContentAsByteArray()); } }; }
/** * Parse the response content as {@link DOMSource} and apply the given * Hamcrest {@link Matcher}. * @see <a href="http://code.google.com/p/xml-matchers/">xml-matchers</a> */ public ResultMatcher source(final Matcher<? super Source> matcher) { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { String content = result.getResponse().getContentAsString(); xmlHelper.assertSource(content, matcher); } }; }
@Test public void userAuthenticates() throws Exception { final String username = "user"; myUserService.insertTestUser(); ResultMatcher matcher = new ResultMatcher() { public void match(MvcResult mvcResult) throws Exception { HttpSession session = mvcResult.getRequest().getSession(); SecurityContext securityContext = (SecurityContext) session.getAttribute(SEC_CONTEXT_ATTR); Assert.assertEquals(securityContext.getAuthentication().getName(), username); } }; mockMvc.perform(post("/signin").param("username", username).param("password", "demo")) .andExpect(redirectedUrl("/")) .andExpect(matcher); }
/** * Assert a flash attribute's value with the given Hamcrest {@link Matcher}. */ public <T> ResultMatcher attribute(final String name, final Matcher<T> matcher) { return new ResultMatcher() { @Override @SuppressWarnings("unchecked") public void match(MvcResult result) throws Exception { assertThat("Flash attribute", (T) result.getFlashMap().get(name), matcher); } }; }
@Test public void userAuthenticateFails() throws Exception { MvcResult res = mockMvc.perform(post("/j_spring_security_check").param("j_username", "user").param("j_password", "")) .andExpect(redirectedUrl("/index.xhtml?login_error=1")) .andExpect(new ResultMatcher() { public void match(MvcResult mvcResult) throws Exception { HttpSession session = mvcResult.getRequest().getSession(); SecurityContext securityContext = (SecurityContext) session.getAttribute(SEC_CONTEXT_ATTR); Assert.assertNull(securityContext); } }).andReturn(); System.out.println(res.getResponse().getRedirectedUrl()); }
/** * Assert the number of flash attributes. */ public <T> ResultMatcher attributeCount(final int count) { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { assertEquals("FlashMap size", count, result.getFlashMap().size()); } }; }
/** * Assert the name of the controller method that processed the request. * <p>Use of this method implies annotated controllers are processed with * {@link RequestMappingHandlerMapping} and {@link RequestMappingHandlerAdapter}. */ public ResultMatcher methodName(final String name) { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { Object handler = assertHandlerMethod(result); assertEquals("HandlerMethod", name, ((HandlerMethod) handler).getMethod().getName()); } }; }
/** * Assert whether asynchronous processing started, usually as a result of a * controller method returning {@link Callable} or {@link DeferredResult}. * <p>The test will await the completion of a {@code Callable} so that * {@link #asyncResult(Matcher)} can be used to assert the resulting value. * Neither a {@code Callable} nor a {@code DeferredResult} will complete * processing all the way since a {@link MockHttpServletRequest} does not * perform asynchronous dispatches. */ public ResultMatcher asyncStarted() { return new ResultMatcher() { @Override public void match(MvcResult result) { HttpServletRequest request = result.getRequest(); assertAsyncStarted(request); } }; }
/** * Assert that asynchronous processing was not started. * @see #asyncStarted() */ public ResultMatcher asyncNotStarted() { return new ResultMatcher() { @Override public void match(MvcResult result) { HttpServletRequest request = result.getRequest(); assertEquals("Async started", false, request.isAsyncStarted()); } }; }
/** * Assert the result from asynchronous processing with the given matcher. * <p>This method can be used when a controller method returns {@link Callable} * or {@link WebAsyncTask}. */ public <T> ResultMatcher asyncResult(final Matcher<T> matcher) { return new ResultMatcher() { @Override @SuppressWarnings("unchecked") public void match(MvcResult result) { HttpServletRequest request = result.getRequest(); assertAsyncStarted(request); assertThat("Async result", (T) result.getAsyncResult(), matcher); } }; }
/** * Assert the result from asynchronous processing. * <p>This method can be used when a controller method returns {@link Callable} * or {@link WebAsyncTask}. The value matched is the value returned from the * {@code Callable} or the exception raised. */ public <T> ResultMatcher asyncResult(final Object expectedResult) { return new ResultMatcher() { @Override public void match(MvcResult result) { HttpServletRequest request = result.getRequest(); assertAsyncStarted(request); assertEquals("Async result", expectedResult, result.getAsyncResult()); } }; }
@Test public void userAuthenticationFails() throws Exception { final String username = "user"; mockMvc.perform(post("/signin").param("username", username).param("password", "invalid")) .andExpect(redirectedUrl("/signin?error")) .andExpect(new ResultMatcher() { public void match(MvcResult mvcResult) throws Exception { HttpSession session = mvcResult.getRequest().getSession(); SecurityContext securityContext = (SecurityContext) session.getAttribute(SEC_CONTEXT_ATTR); Assert.assertNull(securityContext); } }); }
/** * Assert a request attribute value. */ public <T> ResultMatcher attribute(final String name, final Object expectedValue) { return new ResultMatcher() { @Override public void match(MvcResult result) { assertEquals("Request attribute '" + name + "'", expectedValue, result.getRequest().getAttribute(name)); } }; }
/** * Assert a session attribute value with the given Hamcrest {@link Matcher}. */ public <T> ResultMatcher sessionAttribute(final String name, final Matcher<T> matcher) { return new ResultMatcher() { @Override @SuppressWarnings("unchecked") public void match(MvcResult result) { T value = (T) result.getRequest().getSession().getAttribute(name); assertThat("Session attribute '" + name + "'", value, matcher); } }; }
/** * Asserts the request was redirected to the given URL. * <p>This methods accepts only exact matches. * @param expectedUrl the exact URL expected */ public static ResultMatcher redirectedUrl(final String expectedUrl) { return new ResultMatcher() { @Override public void match(MvcResult result) { assertEquals("Redirected URL", expectedUrl, result.getResponse().getRedirectedUrl()); } }; }
/** * Evaluate the XPath and assert the {@link Node} content found with the * given Hamcrest {@link Matcher}. */ public ResultMatcher node(final Matcher<? super Node> matcher) { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { MockHttpServletResponse response = result.getResponse(); xpathHelper.assertNode(response.getContentAsByteArray(), getDefinedEncoding(response), matcher); } }; }
@Test public void userAuthenticates() throws Exception { mockMvc.perform(post("/j_spring_security_check").param("j_username", "ybroche").param("j_password", "adminpass123")) .andExpect(new ResultMatcher() { public void match(MvcResult mvcResult) throws Exception { HttpSession session = mvcResult.getRequest().getSession(); SecurityContext securityContext = (SecurityContext) session.getAttribute(SEC_CONTEXT_ATTR); Assert.assertEquals(securityContext.getAuthentication().getName(), "ybroche"); } }); }
/** * Tests if the response contains the JSON representation of an object of the given type. * * @param clazz the class of the expected object. * @param <T> the type of the expected object. * @return ResultMatcher that performs the test described above. */ public static <T> ResultMatcher containsResource(Class<T> clazz) { return result -> { String json = result.getResponse().getContentAsString(); try { T object = JsonHelper.fromJson(json, clazz); assertThat(object).isNotNull(); } catch (Exception e) { throw new RuntimeException( String.format("expected JSON representation of class %s but found '%s'", clazz, json), e); } }; }