You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grails 4.0.3单元测试:内存库保存实体后删除操作异常问题

问题:删除已存在的Metafile时返回404错误

我为文件管理器API编写单元测试,第一个测试方法验证从不存在的part中删除文件的场景,代码如下:

void "Deleting a file from a non existent part" (){
        when:
        request.method = 'DELETE'
        request.setParameter("partId","1234567891011")
        request.setParameter("fileId","65465654546654654")
        controller.deleteMetafiles()

        then:
        response.status == 404
        response.json.message == "Part not found."
        //println(response.getJson())
    }

该测试运行符合预期。

接下来我尝试测试删除已插入内存数据库的Metafile,但请求始终返回404(提示"Part not found"),和第一个测试的响应一致,明明已经在given块中创建了Metafile。测试代码如下:

void "Deleting a valid file from an existent part" (){
        given:
        new Metafile(id: '1111111111', filename: 'test.pdf', title: '',
                description: '', uploadedOn: new Date(),
                partId: '2222222222', uploadedBy: 'Alfred', userId: '333333333').save()

        when:
        setupSpec()
        request.method = 'DELETE'
        request.setParameter("partId","2222222222")
        request.setParameter("fileId","1111111111")
        def model = controller.deleteMetafiles()

        then:
        response.status == 200


        println("response status")
        println(response.status)
        println("response status")
    }

附完整测试代码:

package br.gov.cmb.cmbarq.tests

import br.gov.cmb.cmbarq.controllers.v1.MetafileController
import br.gov.cmb.cmbarq.domain.Metafile
import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification
import grails.testing.gorm.DataTest

class MetafileControllerSpec extends Specification implements ControllerUnitTest<MetafileController>, DataTest{
    def setupSpec() {
    }

    def cleanup() {
    }

    void "Getting the amount of files from a non existent part"() {
        when:
        request.method = 'GET'
        request.setParameter("partId","1234567891011")
        controller.getMetafilesAmount()

        then:
        response.status == 404

    }

    void "Listing files of an non existent part"() {
        when:
        request.method = 'GET'
        request.setParameter("partId","1234567891011")
        controller.listMetafiles()
        then:
        response.status == 404

    }

    void "Deleting a file from a non existent part" (){
        when:
        request.method = 'DELETE'
        request.setParameter("partId","1234567891011")
        request.setParameter("fileId","65465654546654654")
        controller.deleteMetafiles()

        then:
        response.status == 404
        response.json.message == "Part not found."
        //println(response.getJson())
    }


    void "Deleting a valid file from an existent part" (){
        given:
        List <Metafile> sampleMetafiles = [new Metafile(id: '1111111111', filename: 'test.pdf', title: '',
                description: '', uploadedOn: new Date(),
                partId: '2222222222', uploadedBy: 'Alfred', userId: '333333333'),
                                           new Metafile(id: '1111111112', filename: 'test2.pdf', title: '',
                                                   description: '', uploadedOn: new Date(),
                                                   partId: '2222222221', uploadedBy: 'Alfred', userId: '333333334')
                ]


        when:
        request.method = 'DELETE'
        request.setParameter("partId","2222222222")
        request.setParameter("fileId","1111111111")
        controller.deleteMetafiles()

        then:
        println(model.size())
        model.size() == 1


    }   
}

错误原因及修复方案

  1. 未持久化Metafile实例
    在完整测试代码的目标测试方法中,仅创建了sampleMetafiles列表,但没有调用save()方法将实例存入内存数据库,导致控制器无法查询到对应数据。

  2. 错误调用生命周期方法
    在单独测试代码的when块中手动调用了setupSpec(),这是Spock的全局初始化方法,会在所有测试执行前运行一次,手动调用会重置测试状态,清空已保存的数据。

  3. 未注册测试域类
    实现DataTest接口时,需要注册要测试的域类,否则GORM无法识别Metafile,导致保存操作不生效。

修复后的测试代码示例

void "Deleting a valid file from an existent part" (){
        given:
        // 保存Metafile到内存数据库,failOnError确保保存失败时抛出异常
        new Metafile(id: '1111111111', filename: 'test.pdf', title: '',
                description: '', uploadedOn: new Date(),
                partId: '2222222222', uploadedBy: 'Alfred', userId: '333333333').save(failOnError: true)

        when:
        request.method = 'DELETE'
        request.setParameter("partId","2222222222")
        request.setParameter("fileId","1111111111")
        controller.deleteMetafiles()

        then:
        response.status == 200
        // 验证文件已被删除
        Metafile.countByPartIdAndId('2222222222', '1111111111') == 0
    }

类层面的补充修复

在测试类的setupSpec()中注册域类:

class MetafileControllerSpec extends Specification implements ControllerUnitTest<MetafileController>, DataTest{
    def setupSpec() {
        // 注册要测试的域类
        mockDomain(Metafile)
    }

    // 其他测试方法...
}

内容的提问来源于stack exchange,提问作者D Nunes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 12:03:37