1、dbunit 字段不能为空的问题
dbUnit / Bugs / #363 Regression: cannot insert an empty string
- 为啥要这样做?在实际的数据表中有text类型的字段,值是可以为空字符串或者null的
2、spock commit 后格式错乱的问题,留一行即可解决
4、按照目前的idea plugin 开发一套适合spock格式的dbunit插件
:::tips
skill (skill_id: “4”,skill_name: “家居安装维修”,parent_id: “0”,sort: “1”,level: “1”,create_time: “1614061455573”,update_time: “1644839217688”)
:::
dbunit-extractor.jar.zip
使用的时候把zip去掉,再导入到idea中
5、mybatis 一级缓存导致的脏读:
场景:在使用spock时发现的一个问题
public class BusinessService{
public void setSelfOwned(BusinessSelfOwnedDTO dto) {
Business business = businessMapper.selectById(dto.getBusinessId());
ApiException.throwError(null == business, ApiErrorCode.BUSINESS_NOT_FOUND);
business.setIsSelfOwned(dto.getIsSelfOwned());
// businessMapper.updateById(business);
}
}
@Unroll
def "test setSelfOwned"() {
given:
def ownedDTO = new BusinessSelfOwnedDTO(businessId: businessId, isSelfOwned: isSelfOwned)
when:
businessService.setSelfOwned(ownedDTO)
then:
def business = businessService.businessMapper.selectById(businessId)
business.getIsSelfOwned() == isSelfOwned
println(business)
where:
businessId | isSelfOwned
1 | 1
1 | 0
1 | 0
}
发现无论怎么都是 pass
解决方案:
配置 localCacheScope
public class DataSourceHolder {
// public static SqlSessionFactory builder = new MybatisSqlSessionFactoryBuilder().build(DataSourceHolder.class.getClassLoader().getResourceAsStream("mybatis-config.xml"));
public static SqlSessionFactory builder;
public static Configuration configuration;
public static DataSource dataSource = SpecUtils.inMemoryDataSource();
static {
//这种方式主要是为了兼容dbUnit
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
try {
factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
factory.setDataSource(SpecUtils.inMemoryDataSource());
builder = factory.getObject();
MybatisConfiguration configurationT = (MybatisConfiguration) builder.getConfiguration();
//解决一级缓存导致的脏读
//场景: 下面方法中没有update,在重复单元测试时发现查询出来的数据竟然是缓存的数据
/*public void setSelfOwned(BusinessSelfOwnedDTO dto) {
Business business = businessMapper.selectById(dto.getBusinessId());
ApiException.throwError(null == business, ApiErrorCode.BUSINESS_NOT_FOUND);
business.setIsSelfOwned(dto.getIsSelfOwned());
//businessMapper.updateById(business);
}
*/
configurationT.setLocalCacheScope(LocalCacheScope.STATEMENT);
GlobalConfig globalConfig = configurationT.getGlobalConfig();
globalConfig.setMetaObjectHandler(new MybatisPlusHandler());
configuration = builder.getConfiguration();
} catch (Exception e) {
throw new RuntimeException(e);
}
//这里是原mybatis的方式
// SqlSessionFactory builder = new SqlSessionFactoryBuilder().build(SkillServiceImplSpec.class.getClassLoader().getResourceAsStream("mybatisTestConfiguration/mybatis-config.xml"));
//这里是mybatisPlus 封装后的
// 作用一:处理entity类和mysql中字段不一致的问题,java中是驼峰式,java是下划线
// 作用二:处理mapper 继承 baseMapper 原mapper没有baseMapper中封装的statement
// 缺点一:因为是非spring模式,在启动后所有的插件都会失效
//解决非spring模式下导致metaObjectHandler缺失的问题,主要就是新增或者更新时,自动填充字段的问题
/*MybatisConfiguration configurationT = (MybatisConfiguration) DataSourceHolder.builder.getConfiguration();
GlobalConfig globalConfig = configurationT.getGlobalConfig();
globalConfig.setMetaObjectHandler(new MybatisPlusHandler());
configuration = DataSourceHolder.builder.getConfiguration();*/
}
public static void initTable() {
String sql = FileUtil.readString("classpath:test/db/init_table.sql", StandardCharsets.UTF_8);
new Sql(dataSource).execute(sql);
}
}
MyBatis一级缓存_xinyuan_java的博客-CSDN博客_mybatis localcachescope
spock
6、spock单元测试框架的使用
@SpringBootTest
@ContextConfiguration(classes = UserServiceImpl.class)
@WebAppConfiguration
class UserInfoSpec extends Specification {
@Autowired
UserServiceImpl userService
@SpringBean
UserMapper userMapper = Mock()
def setup() {}
@Unroll
def "testSelectUserById"() {
given:
def user = new User(userId: userId, userName: userName, passWord: passWord);
userMapper.seleteUserById(userId) >> user
expect:
userService.selectUserById(userId) == user
where:
userId | userName | passWord
1234567L | xiaoming | 123456
12309756 | xiaohong | 4321134
}
}
作者:hancaicai
链接:https://ld246.com/article/1573907697146
来源:链滴
协议:CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/
参考:
定位
@Unroll("非法用户名:#exampleUsername")
def "用户名需是2-16位数字、字母和中文混合"() {
when: "初始化用户名"
username = new Username(exampleUsername)
then: "不符合规则时抛出异常"
thrown(IllegalArgumentException)
where:
exampleUsername << [
"1",
"12345678901234561",
"杜",
"国破山河在凑足十七个个字才行啊是不",
"有符号 。 所以不行",
"英文.符号所以不行",
"有空格 不行",
"",
]
}
项目参考:
GitHub - imcamilo/kotlin-spring-project: Kotlin + MyBatis + Spock + Spring Boot + Docker
Spock单元测试框架介绍以及在美团优选的实践
Spock系列 - 老K的Java博客
github上的spock实战项目
GitHub - lucas-myx/spock_example: Spock是国外一款功能强大的测试框架,但是官方的文档和代码示例不太适合我们实际的工程项目,无法解决我们项目中的复杂业务场景,需要找到一套适合自己项目的成熟解决方案,所以觉得有必要把我们项目中使用Spock的经验分享出来,帮助大家解决实际问题或带来一些启发,如果你在使用过程中遇到问题可以在公众号[Java老K]或我的博客 //javakk.com 交流沟通
@Unroll
def "test login with "(){
when:
userService.login(name, passwd)
then:
userDao.findByName("k") >> null
userDao.findByName("k1") >> new User("k1", 12, "p")
then:
def e = thrown(RuntimeException)
e.message == errMsg
where:
name | passwd | errMsg
"k" | "k" | "${name}不存在"
"k1" | "p1" | "${name}密码输入错误"
}
使用mybatisplus参考文章:
MyBatis Plus_Kramer_149的博客-CSDN博客
记载一下成功后的案例:
import com.alibaba.testable.core.annotation.MockDiagnose
import com.alibaba.testable.core.model.LogLevel
import com.baomidou.mybatisplus.core.MybatisConfiguration
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder
import org.apache.ibatis.session.SqlSessionFactory
import spock.lang.Specification
import spock.lang.Unroll
/*// 注意这里要使用 unittest 的配置文件了,里面使用H2数据库
@ActiveProfiles("unittest")
// 关于@Rollback(false)注解:正常情况下,SpringBoot的测试用例每执行完一个就会回滚一次,
// 比如说再执行完create entity test之后会立马将刚刚insert进去的数据清除,之后执行“get entity test”的时候应该是测试用例不通过的。
// 加了这个注解后,就可以指定某个测试方法,或者某个测试类的执行结果不进行回滚。
@Rollback
@MybatisPlusTest*/
//@ActiveProfiles("unittest")
//@MybatisPlusTest
class SkillServiceImplSpec extends Specification {
private SkillServiceImpl skillService;
void setup() {
//这里是原mybatis的方式
// SqlSessionFactory builder = new SqlSessionFactoryBuilder().build(SkillServiceImplSpec.class.getClassLoader().getResourceAsStream("mybatisTestConfiguration/SkillMapperTestConfiguration.xml"));
//这里是mybatisPlus 封装后的
// 作用一:处理entity类和mysql中字段不一致的问题,java中是驼峰式,java是下划线
// 作用二:处理mapper 继承 baseMapper 原mapper没有baseMapper中封装的statement
// 缺点一:因为是非spring模式,在启动后所有的插件都会失效
SqlSessionFactory builder = new MybatisSqlSessionFactoryBuilder().build(SkillServiceImplSpec.class.getClassLoader().getResourceAsStream("mybatisTestConfiguration/SkillMapperTestConfiguration.xml"));
//解决非spring模式下导致metaObjectHandler缺失的问题,主要就是新增或者更新时,自动填充字段的问题
def configuration = (MybatisConfiguration) builder.getConfiguration()
configuration.getGlobalConfig().metaObjectHandler = new MybatisPlusHandler();
// //you can use builder.openSession(false) to not commit to database
SkillMapper mapper = builder.getConfiguration().getMapper(SkillMapper.class, builder.openSession(true));
skillService = new SkillServiceImpl();
skillService.baseMapper = mapper
skillService.skillMapper = mapper
skillService.skillConverter = new SkillConverterImpl();
skillService.groupServiceMenuMapper = Stub(GroupServiceMenuMapper)
skillService.workerSkillRelationMapper = Stub(WorkerSkillRelationMapper)
}
@MockDiagnose(LogLevel.VERBOSE)
public static class Mock {
}
@Unroll
def "test save"() {
given: "修改3级"
def dto = new SkillSaveDto(skillId: 3, skillName: "新三级名称", parentId: 2, level: 3)
when: "不存在服务菜单数据,不存在服务数据"
skillService.save(dto)
then:
println "执行成功"
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Mybatis config sample -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default = "default">
<environment id="default">
<transactionManager type="JDBC"/>
<dataSource type="UNPOOLED">
<property name = "driver" value = "com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://"/>
<property name="username" value=""/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/SkillMapper.xml"/>
</mappers>
</configuration>
dbunit 参考:
https://github.com/janbols/spock-dbunit
驼峰转下划线:
在线工具-驼峰转下划线,下划线转驼峰-BeJSON.com
有赞单元测试实践