package com.softwaremill.common.dbtest; import org.mockito.cglib.proxy.Factory; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import java.util.Arrays; import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; import static java.lang.String.format; import static org.testng.Assert.assertTrue; /** * Extends Mockito with a few helpful methods. * * @author Maciej Bilas * @since 10/20/11 11:42 */ public class MockitoPersistence { private static class LazyValidatorHolder { public static Validator instance = Validation.buildDefaultValidatorFactory().getValidator(); } private static Validator getValidator() { return LazyValidatorHolder.instance; } private MockitoPersistence() { /* this class should not be instantiated */ } /** * Can be used with typical DAO {@code persist(entity)} method. * <p/> * Validations are run as part of the mocked persist operation. If they fail an assertion error is thrown. * <p/> * Example usage: * {@code when(yourDao.persist(any(BaseEntity.class)).thenAnswer(persistAnswer())} * <p/> * The Answer assumes that persist method returns the persisted object. * * @param <T> type of the entities persisted. Just to make the type system happy. * @return the {@link Answer} object. */ public static <T> Answer<T> persistAnswer() { return new Answer<T>() { @Override @SuppressWarnings("unchecked") public T answer(InvocationOnMock invocation) throws Throwable { T entity = (T) invocation.getArguments()[0]; Set<ConstraintViolation<T>> constraintViolations = getValidator().validate(entity); assertTrue(constraintViolations.isEmpty(), format("Entity %s could not be persisted.\n" + "Violations: %s.", entity.toString(), Arrays.toString(constraintViolations.toArray()))); return (T) invocation.getArguments()[0]; } }; } /** * Can be used to mock DAO's reload() method. * <p/> * Basically this method only returns the parameter passed as the first argument. * * @param <T> just to make the type system happy * @return the {@link Answer} object. */ public static <T> Answer<T> reloadAnswer() { return new Answer<T>() { @Override @SuppressWarnings("unchecked") public T answer(InvocationOnMock invocation) throws Throwable { T entity = (T) invocation.getArguments()[0]; return entity; } }; } }