I had almost the same problems as yours, and I changed my class, which contains the specifications as an object, and not just one class with static methods. That way, I can easily mock it, use dependency injection to pass it on, and check which methods were called (without using PowerMockito to mock static methods).
If you want to do what I did, I recommend that you check the specifications with the integration tests, and for the rest, simply if the correct method was called.
For instance:
public class CdrSpecs { public Specification<Cdr> calledBetween(LocalDateTime start, LocalDateTime end) { return (root, query, cb) -> cb.between(root.get(Cdr_.callDate), start, end); } }
Then you have an integration test for this method, which checks whether the method is correct or not:
@RunWith(SpringRunner.class) @DataJpaTest @Sql("/cdr-test-data.sql") public class CdrIntegrationTest { @Autowired private CdrRepository cdrRepository; private CdrSpecs specs = new CdrSpecs(); @Test public void findByPeriod() throws Exception { LocalDateTime today = LocalDateTime.now(); LocalDateTime firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth()); LocalDateTime lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth()); List<Cdr> cdrList = cdrRepository.findAll(specs.calledBetween(firstDayOfMonth, lastDayOfMonth)); assertThat(cdrList).isNotEmpty().hasSize(2); }
And now, when you want to unit test other components, you can test this, for example:
@RunWith(JUnit4.class) public class CdrSearchServiceTest { @Mock private CdrSpecs specs; @Mock private CdrRepository repo; private CdrSearchService searchService; @Before public void setUp() throws Exception { initMocks(this); searchService = new CdrSearchService(repo, specs); } @Test public void testSearch() throws Exception {
And, of course, inside the Service you can still use the where and and static methods of the specification class.
Hope this helps you.