-
Notifications
You must be signed in to change notification settings - Fork 38.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support AssertJ variant in MockMvc [SPR-16637] #21178
Comments
I've put together a library that offers AssertJ assertions for |
I have read the comments in the other post (about SB), why not work around two branches? One for Hamcrest (Keeping the current available approach) and the other one for AssertJ ... Sadly Hamcrest is very verbose to test data about returned data either in XML or JSON. |
Hello @sbrannen here for your consideration. Thanks for your understanding |
+1 |
I've been thinking about this, and I'm not sure that we need to add explicit support for AssertJ in order to allow people to choose to use AssertJ, Truth, or any other assertion framework. For example, if we introduce generic "consumer" support (as in mockMvc.perform(get("/users"))
.andExpect(model().attribute("userList", List.class),
list -> assertThat(list).hasSize(2)));
|
A quick local spike with the following new method in public <T> ResultMatcher attribute(String name, Class<T> requiredType, Consumer<T> valueConsumer) {
return result -> {
ModelAndView mav = getModelAndView(result);
T value = (T) ClassUtils.resolvePrimitiveIfNecessary(requiredType).cast(mav.getModel().get(name));
valueConsumer.accept(value);
};
} ... results in the following working test case, modified from Spring's test suite. @Test
public void testAttributeEqualTo() throws Exception {
mockMvc.perform(get("/"))
// Hamcrest
.andExpect(model().attribute("integer", equalTo(3)))
// AssertJ
.andExpect(model().attribute("integer", int.class, num -> assertThat(num).isEqualTo(3)));
} The "consumer" variant is obviously considerably more verbose, but it shows that it's possible to provide such generic functionality with the current building blocks in |
That's good to know we could provide hooks. One of the more annoying aspects of trying to create this type of assertion is that you really need to expose |
Indeed, it does look nice: fluent! But I agree that forcing people to have AssertJ on the classpath is a major drawback. So, if we do anything AssertJ-specific, we should do our best to ensure that AssertJ remains an optional dependency. |
@philwebb would it be possible to use a wrapper class that checks if AssertJ is available on the classpath and if not, falls back to hamcrest? That way AssertJ could remain optional. Something like https://stackoverflow.com/questions/11432212/java-class-with-possibly-missing-run-time-dependencies |
I'm not sure what you mean by falling back to Hamcrest. The Hamcrest and AssertJ APIs are not compatible. So any explicit support for AssertJ would have to be in addition to the existing Hamcrest support. |
Sorry. Wrong wording. I was just trying to propose a possible solution that would keep AssertJ optional. |
Hello Sam
Even when they are not compatible, seems an important goal is create a common API to change smoothly a technology to other quickly (i.e: Hamcrest to AssertJ) and let add a new technology (i.e:Truth or other in the future). Seems You and Phill are the experts ... If is not possible create a common API (seems is very hard for this situation) perhaps JUnit 5 would play an important role how a kind of |
Unfortunately not because we need a specific type available at compile time so that the IDE can offer code completion. I faced the same problem with
That probably means we either need an AssertJ specific version of MockMvc, or we end up with a sub-par API. I'd probably prefer moving this back to Spring Boot if can't make the API fluent. We've already got much stronger opinions about using AssertJ so it might not feel so forced there. |
Right. To achieve a decent API (fluent with code completion a la AssertJ's traditional style), we would either need a specific version of For example, after the invocation of
I still think that the "generic consumer" approach I outlined is worth considering, regardless of whether we support AssertJ directly in |
I'd need to brush up on my classloading knowledge. If |
You might be right: that might not work at all. I'd have to investigate. We do have similar "tricks" in various places in the framework where we work with an "optional" type only-on-demand, but the difference might be that we don't expose the "optional" type directly in those use cases. So I might be confusing those tricks with the scenario here. |
The branching approach seems to work fine. Check out the following feature branch to see it in action. Overview:
Tests:
|
Please note that in my proof of concept, |
Regarding generic assertion hooks in |
Will this be possible in both MockMvcResultMatchers and MockRestRequestMatchers? That would be amazing, the world is so tired of Hamcrest |
If we do something for |
Are there any updates regarding assertj support? |
This is still in the 5.x Backlog for future consideration. |
are there any workarounds to use assertj or even an alternative to mockmvc that supports it? |
You might be happy with the |
This commit moves JSON content AssertJ support from Spring Boot. See gh-21178 Co-authored-by: Brian Clozel <[email protected]>
This commit moves JSON path AssertJ support from Spring Boot. See gh-21178 Co-authored-by: Brian Clozel <[email protected]>
This commit adds AssertJ compatible assertions for HTTP request and responses, including headers, media type, and response body. The latter delegate to the recently included JSON assert support. See gh-21178
This commit adds AssertJ compatible assertions for the component that produces the result from the request. See gh-21178
This commit adds AssertJ compatible assertions for the Model that is generated from an HTTP request. See gh-21178
This commit adds AssertJ compatible assertions for cookies See gh-21178 Co-authored-by: Brian Clozel <[email protected]>
This commit adds a new way to use MockMvc by returning a MvcResult that is AssertJ compatible. Compared to the existing MockMvc infrastructure, this new model has the following advantages: * Can be created from a MockMvc instance * Dedicated builder methods for easier setup * Assertions use familiar AssertJ syntax with discoverable assertions through a DSL * Improved exception message See gh-21178 Co-authored-by: Brian Clozel <[email protected]>
... which drags So all this effort, and we kinda ended up where we started?! EDIT: ¹ |
Brian Clozel opened SPR-16637 and commented
This Spring Boot issue shows that many developers would like to use AssertJ-style assertions with MockMvc. This would also be a nice complement to the existing Kotlin support, since Kotlin users seem to favor this style of assertions.
The linked Spring Boot issue contains a fairly advanced branch with a working prototype.
Reference URL: spring-projects/spring-boot#5729
8 votes, 12 watchers
The text was updated successfully, but these errors were encountered: