Question

I'm using QueryDSL 3.2.4 with Spring Data JPA 1.4.2 serving as my Repository layer. I have a class to take my web form object (a simple Bean that Spring binds the search form to) and generate the QueryDSL Criteria object for it, which then gets passed to the business/data layer to run the query.

I'm trying to figure out the best way to unit test this generation of a Criteria object. Depending on what is being searched for, different combinations of fields will be in the query (Basically, the typical search form, where fields can be blank to not constrain based on it, but each non-blank field indicates a search criterion, and some fields may have some additional options such as whether it's for "exact match", "starts with", or "contains".)

There's a Spring Data JPA tutorial which advocates for the use of QueryDSL over JPA Criteria API, in part because one can unit test QueryDSL just by comparing the .toString(). So, that's the way I'm leaning toward for now, of making sure that the resulting Criteria object's toString() is reasonable for the query I'm trying to test, but I'm not sure how I'd get the "expected" toString without constructing the desired query ahead of time and seeing what its toString is, so it feels like not a great test, and it feels like it's based on the internals of QueryDSL which may be subject to change. (I think of toString on most classes as mainly being a debugging aid, not a part of the spec, though if somebody pointed me to a spec on how QueryDSL creates its toString() methods and that it's part of the way to use and/or test usage of the library, I think I'd be a lot happier with this approach.) I'm hoping there's something better.

There's another StackOverflow question "How do I unit test the querydsl query inside the given method?", but that looks to be about testing entire queries and needing a mock EntityManager. I'm hoping to just test the Criteria part, so I'm hoping there's a simpler approach than that, where I'd need to mock up a Query that's using the Criteria and then a mock EntityManager to use it, and that all looks to me more complicated than what I'm trying to do for just unit testing that I'm creating a Criteria object correctly.

I feel like I can't be the only person trying to test that I'm creating the right Criteria. Thanks for any insights you may have into what I'm doing wrong or how one can unit test this better.

Was it helpful?

Solution

My approach for this is to start with simple queries and then collect more and more complex "samples". Yes, I'm using the actual query result and copy that into the expected part of my unit tests after eyeballing it.

This isn't a great test; the purpose is slightly different: It documents what you expect.

When something changes, your tests will start to fail and you can create a diff between "what I expected yesterday" and "what I get today."

This also documents what your code is capable of. When a bug in production is discovered, you can try to write a new unit test and see how many others are also failing. This gives you good understanding of the impact of a change (1 change + 90% of the tests fail? You found a hot spot!)

When I fix bugs, I start to see patterns what usually goes wrong and I can protect those places with specific unit tests (like in sub builders used by the big query builder).

For a few complex queries, I create unit tests to see if they would actually work. That gives me the confidence that the quick "string compare" unit tests work.

OTHER TIPS

I 'unit' test all of my QueryDSL code with a real EntityManager and a real in memory H2 database. No mocking of the EntityManager and no checking the generated JPQL, I test that the query actually returns the objects I expect.

The Unit Testing purists could argue that this is not a true unit test but I have code that works and it is quick enough.

This is fairly easily achieved with springs embedded database support:

<jdbc:initialize-database data-source="dataSource">
  <jdbc:script location="classpath:com/foo/sql/db-schema.sql"/>
</jdbc:initialize-database>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top