package org.springframework.data.simpledb.query;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.simpledb.annotation.Query;
import org.springframework.data.simpledb.attributeutil.SimpleDBAttributeConverter;
import org.springframework.data.simpledb.core.SimpleDbDomain;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
public class SimpleDbNamedQueryMethodBindedTest {
// Methods testing the Named Query Replacement via @Query.select && @Query.where() clauses
@Test
public void buildQueryConditionsWithParameters_should_work_with_the_same_placeholder_values_as_fieldkeys()
throws Exception {
// @Query(select = {"item_id", "sampleAttribute"}, where =
// "sampleAttribute<=:sampleAttribute and item_id = :item_id")
final String expectedQuery = "select item_id, sampleAttribute from `testDB.sampleEntity` where sampleAttribute<='3' and item_id = '5'";
SimpleDbQueryMethod repositoryMethod = prepareQueryMethodToTest("selectWithEqualPlaceholders",
SampleEntity.class);
final String toProcessRawQuery = repositoryMethod.getAnnotatedQuery();
final Parameters parameters = getMockParameters(new String[]{":sampleAttribute", ":item_id"}, new Class[]{String.class, String.class});
String resultedQuery = QueryUtils.buildQuery(toProcessRawQuery, parameters, "3", "5");
assertThat(resultedQuery, is(expectedQuery));
}
@Test
public void buildQueryConditionsWithParameters_should_work_with_different_placeholder_values_as_fieldkeys()
throws Exception {
// @Query(select = {"item_id", "sampleAttribute"}, where = "sampleAttribute<=:attribute and item_id = :item")
final String expectedQuery = "select item_id, sampleAttribute from `testDB.sampleEntity` where sampleAttribute<='3' and item_id = '5'";
SimpleDbQueryMethod repositoryMethod = prepareQueryMethodToTest("selectWithDifferentPlaceholders",
SampleEntity.class);
final String toProcessRawQuery = repositoryMethod.getAnnotatedQuery();
final Parameters parameters = getMockParameters(new String[]{":attribute", ":item"}, new Class[]{String.class, String.class});
String resultedQuery = QueryUtils.buildQuery(toProcessRawQuery, parameters, "3", "5");
assertThat(resultedQuery, is(expectedQuery));
}
@Test
public void buildQueryConditionsWithParameters_should_work_with_primitive_type_parameter_values() throws Exception {
// @Query(select = {"item_id", "sampleAttribute"}, where = "sampleAttribute<=:attribute and item_id = :item")
final int age = 5;
final String convertedAge = SimpleDBAttributeConverter.encode(age);
final String expectedQuery = "select item_id, sampleAttribute from `testDB.sampleEntity` where sampleAttribute<='3' and item_id = '"
+ convertedAge + "'";
SimpleDbQueryMethod repositoryMethod = prepareQueryMethodToTest("selectWithDifferentPlaceholders",
SampleEntity.class);
final String toProcessRawQuery = repositoryMethod.getAnnotatedQuery();
final Parameters parameters = getMockParameters(new String[]{":attribute", ":item"}, new Class[]{String.class, int.class});
String resultedQuery = QueryUtils.buildQuery(toProcessRawQuery, parameters, "3", 5);
assertThat(resultedQuery, is(expectedQuery));
}
// -------------------------- define methods to work with; Note that the methods arguments are mocked
// ----------------------- //
public interface AnnotatedQueryRepository {
@Query(select = { "item_id", "sampleAttribute" }, where = "sampleAttribute<=:sampleAttribute and item_id = :item_id")
List<SampleEntity> selectWithEqualPlaceholders();
@Query(select = { "item_id", "sampleAttribute" }, where = "sampleAttribute<=:attribute and item_id = :item")
List<SampleEntity> selectWithDifferentPlaceholders();
}
// -------------------------------- Reused/Mocks --------------------------------- //
static final List<Class<?>> TYPES = Arrays.<Class<?>>asList(Pageable.class, Sort.class);
@SuppressWarnings({ "rawtypes", "unchecked" })
private Parameter getMockParameter(String placeHolder, Integer idx, Class clazz) {
Parameter mockParameter = Mockito.mock(Parameter.class);
Mockito.when(mockParameter.getPlaceholder()).thenReturn(placeHolder);
Mockito.when(mockParameter.isNamedParameter()).thenReturn(Boolean.TRUE);
Mockito.when(mockParameter.getIndex()).thenReturn(idx);
Mockito.when(mockParameter.getType()).thenReturn(clazz);
Mockito.when(mockParameter.isSpecialParameter()).thenReturn(TYPES.contains(clazz));
return mockParameter;
}
@SuppressWarnings({ "rawtypes" })
private Parameters getMockParameters(String[] placeHolders, Class[] clazzes) {
Parameters mockParameters = Mockito.mock(Parameters.class);
List<Parameter> parameters = new ArrayList<Parameter>(placeHolders.length);
for(int idx = 0; idx < placeHolders.length; ++idx) {
parameters.add(getMockParameter(placeHolders[idx], idx, clazzes[idx]));
}
Mockito.when(mockParameters.iterator()).thenReturn(parameters.iterator());
Mockito.when(mockParameters.getNumberOfParameters()).thenReturn(parameters.size());
return mockParameters;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private SimpleDbQueryMethod prepareQueryMethodToTest(String methodName, Class<?> entityClass) throws Exception {
RepositoryMetadata repositoryMetadata = Mockito.mock(RepositoryMetadata.class);
when(repositoryMetadata.getDomainType()).thenReturn((Class) entityClass);
Method testMethod = AnnotatedQueryRepository.class.getMethod(methodName);
when(repositoryMetadata.getReturnedDomainClass(testMethod)).thenReturn((Class) entityClass);
SimpleDbDomain simpleDbDomain = new SimpleDbDomain();
return new SimpleDbQueryMethod(testMethod, repositoryMetadata, simpleDbDomain);
}
}