V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shazh520
V2EX  ›  Java

大家在做单元测试的时候如何准备数据库环境?

  •  
  •   shazh520 · 2019-12-11 15:18:56 +08:00 · 9512 次点击
    这是一个创建于 1569 天前的主题,其中的信息可能已经有所发展或是发生改变。

    例如说需要测试一个删除功能,大家是在测试方法的开头插入一条记录以供删除吗?还是什么其他方法?

    还有一种情况是,例如一个电商系统,想测删除 SKU 接口,准备数据的时候就得先准备产品,然后再准备 SKU,大家是如何准备的?

    51 条回复    2020-06-08 18:21:33 +08:00
    shazh520
        1
    shazh520  
    OP
       2019-12-11 15:31:10 +08:00
    V 友求教 求教
    Hanggi
        2
    Hanggi  
       2019-12-11 15:34:14 +08:00   ❤️ 1
    测试没有 before 和 after 吗?通常都是要在测试开头创建数据,结束的时候删掉的。
    BruceLi
        3
    BruceLi  
       2019-12-11 15:34:34 +08:00   ❤️ 1
    mock 一下,单元测试一般不依赖其他接口或者系统。
    shazh520
        4
    shazh520  
    OP
       2019-12-11 15:35:54 +08:00
    @Hanggi 用 jpa 插入数据吗?还是用 SQL 脚本?
    shazh520
        5
    shazh520  
    OP
       2019-12-11 15:36:36 +08:00
    @BruceLi 就是自己的系统啊,测试删除产品接口,那得有一个产品 ID 啊,如何准备这个产品 ID 的问题
    Ahaochan
        6
    Ahaochan  
       2019-12-11 15:48:41 +08:00
    用 h2database,准备初始化 sql 脚本
    shazh520
        7
    shazh520  
    OP
       2019-12-11 15:51:27 +08:00
    @Ahaochan 项目已经用 MySQL 了,现在好像换不了
    KentY
        8
    KentY  
       2019-12-11 15:56:04 +08:00 via iPhone
    google 下 flyway 和 h2
    lihongjie0209
        9
    lihongjie0209  
       2019-12-11 15:58:43 +08:00   ❤️ 1
    有数据库就不叫单元测试了
    zunceng
        10
    zunceng  
       2019-12-11 16:03:21 +08:00
    dao 层做一个 mock 当然也可以用 sqlmock
    chendy
        11
    chendy  
       2019-12-11 16:10:33 +08:00
    既然是单元测试,那就 mock 掉 dao
    否则就脚本塞数据,直接测接口,做集成测试
    greenlaw110
        12
    greenlaw110  
       2019-12-11 16:26:52 +08:00
    mock 是常见的方式, 不过涉及到数据库操作的情况下,mock 总感觉不靠谱. 啥都 mock 了,函数里面也没有什么逻辑, 测试也失去了应有的作用.

    这也是我一直很纠结单元测试的原因之一.

    后来自己折腾出了一套 functional 测试工具, 数据准备与清理工作也不成问题了. 有兴趣的同学可以参考一下这里:
    https://gitee.com/actframework/act-doc/blob/master/cn/test.md#-82-%E5%87%86%E5%A4%87%E6%B8%85%E7%90%86%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE
    shazh520
        13
    shazh520  
    OP
       2019-12-11 17:05:34 +08:00
    @lihongjie0209
    @chendy 感谢 认识上的一个误区
    shazh520
        14
    shazh520  
    OP
       2019-12-11 17:09:02 +08:00
    @KentY 有了新思路
    killergun
        15
    killergun  
       2019-12-11 17:10:59 +08:00
    自己 mock 数据进行单元测试。不实际连接数据库
    phpcxy
        16
    phpcxy  
       2019-12-11 17:11:31 +08:00
    我都是开始测试的时候创建一些记录,然后测试完回滚
    abcbuzhiming
        17
    abcbuzhiming  
       2019-12-11 17:46:42 +08:00
    想问一下,你们本地完全没有数据库的吗?这种涉及到数据库的难道不应该至少本地建个库(或者专门一个数据库服务器)测试一下吗
    fkdog
        18
    fkdog  
       2019-12-11 17:55:14 +08:00
    spring 在测试类上打上 @transactional 注解。
    这样运行完测试方法会自动回滚数据,比 before after 清理资源方式更简单
    mingoing
        19
    mingoing  
       2019-12-11 18:41:11 +08:00
    sqlite 内存模式了解下
    liuzhaowei55
        20
    liuzhaowei55  
       2019-12-11 18:55:43 +08:00
    spring boot + jpa 可使用 @DataJpaTest 注解,会自动回滚。
    lazyfighter
        21
    lazyfighter  
       2019-12-11 19:01:44 +08:00
    我今天刚提问这个问题,之前依赖 mysqlServer,目前依赖 embeddedH2
    slyang5
        22
    slyang5  
       2019-12-11 19:12:37 +08:00
    @Test
    @SqlGroup({
    @Sql("/sql/sql_logic_delete.sql"),
    @Sql(scripts = "/sql/sql_logic_delete_clear.sql", executionPhase=Sql.ExecutionPhase.AFTER_TEST_METHOD) })
    public void featuresLogicDeleteTest() {
    // do ....
    }
    slyang5
        23
    slyang5  
       2019-12-11 19:15:33 +08:00
    @slyang5 语言 JAVA, 框架 spirng
    dengtongcai
        24
    dengtongcai  
       2019-12-11 19:19:47 +08:00 via iPhone
    mock 哇
    janxin
        25
    janxin  
       2019-12-11 19:24:47 +08:00
    单测目前都是 Mock
    kaneg
        26
    kaneg  
       2019-12-11 19:28:43 +08:00 via iPhone
    如果不依赖特定数据库的特性,可以用 h2,完全不依赖运行环境,一次编写,随处运行。
    luozic
        27
    luozic  
       2019-12-11 19:33:57 +08:00
    Java 有不少集成版本的测试 demo 数据库,H2,monogodb,redis 都有对应的,即使没有,按 JDBC 也可以 mock
    daimazha
        28
    daimazha  
       2019-12-11 19:35:05 +08:00
    内嵌
    hantsy
        29
    hantsy  
       2019-12-11 19:48:30 +08:00
    终于看到一个技术帖子了。

    写 Java 测试离不开 JUnit。在 Spring 下写测试比较简单些,Spring 自身带的测试工具很全。
    https://github.com/hantsy/building-restful-apis-with-springmvc-gitbook/blob/master/testing.md (比较老了一点)
    Spring Boot 1.4 中增加了大量工具简化测试: https://github.com/hantsy/building-restful-apis-with-springmvc-gitbook/blob/master/boot-1.4.md

    数据库相关的单元测试可以 Mock 相应的操作(比如 Mock JpaRepsoitory ),集成测试时也需要创建数据库,初始化数据为测试准备,Spring Boot 可以使用嵌入式数据库代替(不用清理数据)。

    Java EE 的测试参考:
    Java EE 6: https://github.com/hantsy/signup-app/tree/master/src/test/java/org/company/test
    Java EE 7: https://github.com/hantsy/ee7-jaxrs-sample/tree/master/vanilla/src/test/java/com/hantsylab/example/ee7/blog
    Java EE 8: https://github.com/hantsy/javaee8-jaxrs-sample/tree/master/backend/src/test/java/com/github/hantsy/ee8sample/rest
    lihuayang
        30
    lihuayang  
       2019-12-11 19:56:38 +08:00
    用 h2。单测前准备好 ddl (新建表)、dml (数据),每次运行单测都加载这两个文件。干净,不会污染测试环境的库。
    p1094358629
        31
    p1094358629  
       2019-12-11 20:42:54 +08:00
    我自己写了一个 basicTemplateTest 基类。模板方法:
    提供了编程式事务,配置 setRollBackOnly().即用 spring 的 jdbc 自动回滚。
    zhuzhibin
        32
    zhuzhibin  
       2019-12-11 21:20:41 +08:00 via iPhone
    你这种场景应该叫验收测试吧 通常是 before 前初始化 after 清除掉咯
    springz
        33
    springz  
       2019-12-11 21:23:00 +08:00
    启动一个 docker,用完关闭。
    springz
        34
    springz  
       2019-12-11 21:23:42 +08:00
    模拟 dao 我也是我纠结的点,还是尽量真实吧。
    AbrahamGreyson
        35
    AbrahamGreyson  
       2019-12-11 21:28:54 +08:00
    主流的方式是在 setup teardown 里准备数据, 清空数据库。

    上面说 mock 的, 楼主就是要测数据库。
    des
        36
    des  
       2019-12-11 21:36:33 +08:00 via Android
    +1 感觉本来就是 curd,mock 了 dao 层就没啥好测的了 😂
    springz
        37
    springz  
       2019-12-11 21:59:17 +08:00
    我一直反对 dao 层单元测试 mock
    avalon0624
        38
    avalon0624  
       2019-12-11 22:39:18 +08:00
    用 migrate,开始前清空数据库,生成符合条件的测试数据
    x66
        39
    x66  
       2019-12-11 23:54:13 +08:00   ❤️ 1
    ```
    单元测试( unit testing ),是指对软件中的最小可测试单元进行检查和验证。
    ```
    都连数据库了,还叫单元测试吗?
    FrankD
        40
    FrankD  
       2019-12-11 23:56:03 +08:00 via Android
    可以用本地数据库
    akira
        41
    akira  
       2019-12-12 00:16:58 +08:00
    @x66 测试测试,没必要纠结称呼
    xuanbg
        42
    xuanbg  
       2019-12-12 06:36:07 +08:00
    SQL 语句本来就或多或少包含逻辑,另外数据结构的调整甚至数据库版本的升级,单元测试都不管的么? mock 数据做单元测试的,怕是没更新过数据库结构吧
    dilu
        43
    dilu  
       2019-12-12 07:52:58 +08:00 via Android
    如果修改了数据库里面的数据 这就叫数据库测试了。当然并没有严格区分,你非要测试也没问题的。
    hmxxmh
        44
    hmxxmh  
       2019-12-12 08:56:12 +08:00 via Android
    @x66 单元测试不都是造假数据吗,要连数据库直接开个测试环境测试吧
    ebingtel
        45
    ebingtel  
       2019-12-12 09:10:29 +08:00
    我是先 dump 一份测试数据库(不含数据),跑单元测试之后,再 drop 掉……
    zhenjiachen
        46
    zhenjiachen  
       2019-12-12 09:19:40 +08:00
    这不是很简单吗?如果用了 Spring 的注解事务,不管是 jpa 还是 mybatis 使用单元测试在方法或者类上面加事务注解测试执行完了不管是失败还是成功都会回滚的啊。注意要用 Spring tx 里面的 Transactional。
    zclHIT
        47
    zclHIT  
       2019-12-12 09:54:26 +08:00
    mock repository 的返回结果,单元测试,顾名思义就是测一个单元。
    (整套流程全跑通那是集成测试。。。
    PoetAndPoem
        48
    PoetAndPoem  
       2019-12-12 10:11:05 +08:00 via Android
    一般 afterclass 做回滚
    shazh520
        49
    shazh520  
    OP
       2019-12-12 15:02:50 +08:00
    我想做的那就是集成测试了,调接口,然后 controller service dao 全部跑,之前误解了,sorry 大伙;
    我现在是单独建一个测试库(现存开发库、测试库、正式库),然后每次启动测试都通过 jpa 自动生成表( hibernate ),然后在 spring boot 的启动任务(放在 test 包中,不会打包到正式代码)中利用 repo 往里面塞准备的数据。
    我不想用 SQL 的原因是我想我在改动 Entity 类的时候能够及时的发现错误,容易维护一些,SQL 的话就只能等执行的时候报错了。
    zhangjiayi1095
        50
    zhangjiayi1095  
       2019-12-16 16:19:08 +08:00
    用的 h2
    sunxiansong
        51
    sunxiansong  
       2020-06-08 18:21:33 +08:00
    测之前 docker 起一个,完了 autoRemove

    缺点就是起停一个 container 差不多要 3 秒
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2752 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 15:28 · PVG 23:28 · LAX 08:28 · JFK 11:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.