Open odrotbohm opened 7 years ago
@olivergierke I don't suppose you have an example test available anywhere that we could steal do you?
@philwebb and @olivergierke : I threw together a little project at https://github.com/habuma/books-mvc-jpa that demonstrates the issue.
Put simply, when you run this app, requests to /books/1
and /books/2
work fine and the Book
object passed into the bookDetail()
method is looked up automatically from the BookRepository
. But in the course of running the BooksControllerTest.bookDetail()
test, it fails to convert the String
path variable to the Book
parameter that is annotated with @PathVariable
.
Thank you, @habuma.
This isn't as simple as hoped as Spring Data's Web support is coupled to its repository infrastructure that isn't set up in a typical Web MVC test.
Using a mock CrudRepository
, there's no RepositoryFactoryInformation
in the application context. This means that the matches check inDomainClassConverter.ToEntityConverter<T>
returns false
as repositories.hasRepositoryFor(targetType.getType())
returns false.
@olivergierke What would you suggest? It looks like we'd need to do something to identify mocked Spring Data repositories in the context and somehow synthesise the RepositoryFactoryInformation
for each of them.
Ping @olivergierke. We could do with some of your expertise here please.
Looks like getting DomainClassConverter
to work without a bootstrapped repository infrastructure is kind of tricky. Here are the most apparent reasons:
findById(…)
involves detailed knowledge of the production repository setup as in the no-mock case, we have to find out what object instance to actually invoke the method on. That's why the repository invoker infrastructure requires dependencies that we can't actually satisfy without the factories — and thus the entire infrastructure — to be present.findById(…)
method can be tweaked to use different wrapper types (Scala's or Vavr's Option
)ToIdConverter
needs to lookup an entity's identifier which in case of some persistence providers might be a quite complex step (JPA's compound identifiers come to mind).We can try to introduce an additional layer of abstraction between DomainClassConverter
and the repository invoking infrastructure and see how far we can take it. I've filed this ticket to keep track of the efforts but I'd definitely vote for postponing this to after Spring Boot / Data 2.0.
There is another sample that demonstrates this with a very simple controller in #12938
I wrote this. That fixes my problem #12938. Let me know if it helps and I'll make a PR.
@ideaplugins If that change fixes your issue then it isn't the one being tracked by this issue. It looks like #12938 should possibly be reopened. What do you think, @snicoll?
@wilkinsona good catch, the scope of this issue has extended and we could do what @ideaplugins has done independently.
https://github.com/spring-projects/spring-data-commons/issues/1605 is the relevant Data Commons issue following the JIRA to GitHub issues migration. It remains open.
Spring Data's
@EnableSpringDataWebSupport
registers a couple of Spring MVC extensions that allow the easy consumption ofPageable
andSort
instances as well as automatic identifier-to-entity conversion.When running a test case with
@WebMvcTest
the auto-configuration that enables this is not activated, which I think is due to the fact that it sort of belongs to Spring Data. However, it fundamentally causes controller methods to behave differently.I think it should be just fine to include
SpringDataWebAutoConfiguration
in the set of auto-configurations applied for@WebMvcTest
as it doesn't strictly require any downstream Spring Data components but would make sure that mock repository beans would be picked up (so that the id-to-entity-conversion works during bean binding) and thePageable
andSort
resolution works.