Created
January 29, 2017 13:38
-
-
Save tq-jappy/ce452d5c2b951bb67b71185a1e2e2b50 to your computer and use it in GitHub Desktop.
MyBatis mappers automated test with Spock/Spring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sample.domain.mapper | |
import org.apache.ibatis.annotations.Delete | |
import org.apache.ibatis.annotations.Insert | |
import org.apache.ibatis.annotations.Select | |
import org.apache.ibatis.annotations.Update | |
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition | |
import org.springframework.beans.factory.annotation.Autowired | |
import org.springframework.boot.test.context.SpringBootTest | |
import org.springframework.context.ApplicationContext | |
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider | |
import org.springframework.core.type.filter.RegexPatternTypeFilter | |
import org.springframework.data.domain.PageRequest | |
import org.springframework.data.domain.Pageable | |
import org.springframework.test.context.ActiveProfiles | |
import org.springframework.transaction.annotation.Transactional | |
import spock.lang.Shared | |
import spock.lang.Specification | |
import spock.lang.Unroll | |
import java.lang.reflect.Field | |
import java.lang.reflect.Method | |
import java.lang.reflect.Modifier | |
import java.time.LocalDateTime | |
import java.util.regex.Pattern | |
@ActiveProfiles("test") | |
@SpringBootTest(classes = [SomeConfig]) | |
@Transactional | |
class MapperSpec extends Specification { | |
static final String mapperPackage = 'sample.domain.mapper' | |
class Fixture { | |
Class<?> mapperClass | |
Method method | |
} | |
@Autowired | |
ApplicationContext context | |
@Shared | |
List<Fixture> fixtures = [] as List | |
def setupSpec() { | |
fixtures = [] as List | |
def provider = new ClassPathScanningCandidateComponentProvider(false) { | |
@Override | |
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { | |
// interface は除外されてしまうため override | |
return beanDefinition.getMetadata().isInterface() | |
} | |
} | |
provider.addIncludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*"))); | |
def allClasses = provider.findCandidateComponents(mapperPackage).collect { | |
Class.forName(it.getBeanClassName()) | |
} | |
allClasses.each { mapperClass -> | |
for (Method method : mapperClass.methods) { | |
if (method.getAnnotation(Select) | |
|| method.getAnnotation(Insert) | |
|| method.getAnnotation(Update) | |
|| method.getAnnotation(Delete)) { | |
def fixture = new Fixture(mapperClass: mapperClass, method: method) | |
fixtures.add(fixture) | |
} | |
// TODO: support @InsertProvider, @UpdateProvider, @DeleteProvider, @SelectProvider | |
} | |
} | |
} | |
@Unroll | |
def "#mapperClass.simpleName #method.name"() { | |
setup: | |
def mapper = context.getBean(mapperClass) | |
when: | |
method.invoke(mapper, createParameters(method.getParameterTypes())) | |
then: | |
noExceptionThrown() | |
where: | |
mapperClass << fixtures.collect { it.mapperClass } | |
method << fixtures.collect { it.method } | |
} | |
Object[] createParameters(Class<?>[] parameterTypes) { | |
def parameters = Arrays.asList(parameterTypes).collect { type -> createObject(type) } | |
println parameters | |
return parameters.toArray(new Object[parameters.size()]) | |
} | |
Object createObject(Class<?> type) { | |
if (type.isPrimitive()) { | |
if (type == int.class) { | |
return 0 | |
} else if (type == long.class) { | |
return 0L | |
} else if (type == boolean.class) { | |
return false; | |
} else { | |
// TODO: | |
throw new UnsupportedOperationException("unsupported type: " + type) | |
} | |
} else if (type.isEnum()) { | |
return type.getEnumConstants()[0] | |
} else { | |
if (type == Integer.class) { | |
return Integer.valueOf(0) | |
} else if (type == Long.class) { | |
return Long.valueOf(0L) | |
} else if (type == Boolean.class) { | |
return Boolean.FALSE; | |
} else if (type == String.class) { | |
return "test" | |
} else if (type == BigDecimal.class) { | |
return BigDecimal.valueOf(0D) | |
} else if (type == Pageable.class) { | |
return new PageRequest(0, 10) | |
} else if (type == LocalDateTime.class) { | |
return LocalDateTime.now() | |
} else if (type == List.class) { | |
return Collections.emptyList() | |
} else if (type == Map.class) { | |
return Collections.emptyMap() | |
} else { | |
Object obj = type.newInstance() | |
for (Field field : type.getDeclaredFields()) { | |
int modifier = field.getModifiers() | |
if (!Modifier.isStatic(modifier) && !Modifier.isFinal(modifier)) { | |
field.setAccessible(true) | |
field.set(obj, createObject(field.getType())) | |
} | |
} | |
return obj | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment