org.test4j.module.database.mocker.MybatisConfigurationMock Maven / Gradle / Ivy
package org.test4j.module.database.mocker;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.test4j.annotations.Mock;
import org.test4j.mock.Invocation;
import org.test4j.mock.MockUp;
import org.test4j.mock.startup.Startup;
import org.test4j.module.database.proxy.Test4JSqlContext;
import org.test4j.tools.commons.StringHelper;
/**
* @author darui.wu
*/
@SuppressWarnings({"rawtypes", "unused"})
public class MybatisConfigurationMock extends MockUp {
static boolean hasMock = false;
/**
* 要mock的class文件默认存在
*/
static boolean classNotFound = false;
private MybatisConfigurationMock() {
hasMock = true;
}
@Mock
public StatementHandler newStatementHandler(Invocation it, Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = it.proceed(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
BoundSql sql = boundSql;
if (sql == null) {
sql = mappedStatement.getSqlSource().getBoundSql(parameterObject);
}
if (sql != null) {
TypeHandlerRegistry typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
Object[] parameters = this.getParameters(it.getTarget(), sql, typeHandlerRegistry);
Test4JSqlContext.addSql(StringHelper.removeBreakingWhiteSpace(sql.getSql()), parameters);
}
return statementHandler;
}
private Object[] getParameters(Configuration configuration, BoundSql boundSql, TypeHandlerRegistry typeHandlerRegistry) {
if (boundSql.getParameterMappings() == null) {
return null;
} else {
return boundSql.getParameterMappings().stream()
.filter(this::isInParameter)
.map(parameterMapping -> parseParameterValue(configuration, typeHandlerRegistry, boundSql, parameterMapping))
.toArray();
}
}
private boolean isInParameter(ParameterMapping parameterMapping) {
return parameterMapping.getMode() != ParameterMode.OUT;
}
/**
* 解析参数值
*
* @param configuration Configuration
* @param typeHandlerRegistry TypeHandlerRegistry
* @param boundSql BoundSql
* @param parameterMapping ParameterMapping
* @return ignore
*/
private Object parseParameterValue(Configuration configuration, TypeHandlerRegistry typeHandlerRegistry, BoundSql boundSql, ParameterMapping parameterMapping) {
Object parameterObject = boundSql.getParameterObject();
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
return boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
return null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
return parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
return metaObject.getValue(propertyName);
}
}
/**
* 对 org.apache.ibatis.session.Configuration 进行mock处理
* 用于在测试中收集mybatis执行的语句
*/
public static void mockMybatisConfiguration() {
if (MybatisConfigurationMock.hasMock || MybatisConfigurationMock.classNotFound) {
return;
}
try {
Class.forName("org.apache.ibatis.session.Configuration");
} catch (ClassNotFoundException e) {
MybatisConfigurationMock.classNotFound = true;
return;
}
Startup.initializing = true;
new MybatisConfigurationMock();
Startup.initializing = false;
}
}