gpt4 book ai didi

grails generated-all '*' 创建损坏的 Controller 测试?脚手架生成是否已损坏?

转载 作者:行者123 更新时间:2023-12-02 03:07:09 25 4
gpt4 key购买 nike

更新 3 - 通过和失败的示例

由于这篇文章的长度,所以不允许我粘贴它们,因此可以在这里找到示例:http://pastebin.com/gMVa4Gd1

更新#2。根据有关更新脚手架插件版本的建议答案,我重新运行了generate-all '*'命令和测试。这是更新后的输出,下面是生成的代码:

| Error Forked Grails VM exited with error
| Environment set to development.....
| Running without daemon...
| Running 2 unit tests...
| Running 2 unit tests... 1 of 2
| Running 2 unit tests... 2 of 2
| Running 2 unit tests... 3 of 3
| Failure: Test the save action correctly persists an instance(AddressControllerSpec)
| org.codehaus.groovy.grails.web.servlet.mvc.exceptions.CannotRedirectException: Cannot redirect for object [Address : (unsaved)] it is not a domain or has no identifier. Use an explicit redirect instead
at AddressController.tt__save_closure9_closure14(AddressController.groovy:43)
at AddressController.$tt__save(AddressController.groovy:40)
at AddressControllerSpec.Test the save action correctly persists an instance(AddressControllerSpec.groovy:54)
| Running 2 unit tests... 4 of 4
| Running 2 unit tests... 5 of 5
| Running 2 unit tests... 6 of 6
| Error 2014-06-06 09:39:45,246 [main] ERROR mvc.GrailsParameterMap - Error processing form encoded PUT request
Message: null
Line | Method
->> 98 | doCall in AddressController$_notFound_closure8_closure12
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 96 | notFound in AddressController
| 56 | $tt__update . . . . . . . in ''
| 98 | $spock_feature_0_5 in AddressControllerSpec
| 138 | invokeMethod . . . . . . in org.spockframework.util.ReflectionUtil
| 330 | invokeRaw in org.spockframework.runtime.BaseSpecRunner
| 311 | invoke . . . . . . . . . in ''
| 285 | invokeFeatureMethod in ''
| 256 | doRunIteration . . . . . in ''
| 138 | invokeMethod in org.spockframework.util.ReflectionUtil
| 91 | invokeTargetMethod . . . in org.spockframework.runtime.extension.MethodInvocation
| 85 | proceed in ''
| 37 | evaluate . . . . . . . . in org.spockframework.runtime.extension.builtin.AbstractRuleInterceptor$1
| 48 | evaluate in grails.test.runtime.TestRuntimeJunitAdapter$1$2
| 38 | intercept . . . . . . . . in org.spockframework.runtime.extension.builtin.TestRuleInterceptor
| 84 | proceed in org.spockframework.runtime.extension.MethodInvocation
| 319 | invoke . . . . . . . . . in org.spockframework.runtime.BaseSpecRunner
| 223 | runIteration in ''
| 214 | initializeAndRunIteration in ''
| 205 | runSimpleFeature in ''
| 199 | doRunFeature . . . . . . in ''
| 138 | invokeMethod in org.spockframework.util.ReflectionUtil
| 330 | invokeRaw . . . . . . . . in org.spockframework.runtime.BaseSpecRunner
| 311 | invoke in ''
| 175 | runFeature . . . . . . . in ''
| 152 | runFeatures in ''
| 112 | doRunSpec . . . . . . . . in ''
| 138 | invokeMethod in org.spockframework.util.ReflectionUtil
| 91 | invokeTargetMethod . . . in org.spockframework.runtime.extension.MethodInvocation
| 85 | proceed in ''
| 37 | evaluate . . . . . . . . in org.spockframework.runtime.extension.builtin.AbstractRuleInterceptor$1
| 74 | evaluate in grails.test.runtime.TestRuntimeJunitAdapter$3$4
| 38 | intercept . . . . . . . . in org.spockframework.runtime.extension.builtin.ClassRuleInterceptor
| 84 | proceed in org.spockframework.runtime.extension.MethodInvocation
| 319 | invoke . . . . . . . . . in org.spockframework.runtime.BaseSpecRunner
| 91 | runSpec in ''
| 82 | run . . . . . . . . . . . in ''
| 63 | run in org.spockframework.runtime.Sputnik
| 127 | runChild . . . . . . . . in org.junit.runners.Suite
| 26 | runChild in ''
| 238 | run . . . . . . . . . . . in org.junit.runners.ParentRunner$3
| 63 | schedule in org.junit.runners.ParentRunner$1
| 236 | runChildren . . . . . . . in org.junit.runners.ParentRunner
| 53 | access$000 in ''
| 229 | evaluate . . . . . . . . in org.junit.runners.ParentRunner$2
| 309 | run in org.junit.runners.ParentRunner
| 160 | run . . . . . . . . . . . in org.junit.runner.JUnitCore
^ 138 | run in ''
| Failure: Test the update action performs an update on a valid domain instance(AddressControllerSpec)
| java.lang.NullPointerException: Cannot get property 'id' on null object
at AddressControllerSpec.Test the update action performs an update on a valid domain instance(AddressControllerSpec.groovy:122)
| Running 2 unit tests... 7 of 7
| Failure: Test that the delete action deletes an instance if it exists(AddressControllerSpec)
| Condition not satisfied:
Address.count() == 1
| |
0 false
at AddressControllerSpec.Test that the delete action deletes an instance if it exists(AddressControllerSpec.groovy:142)
| Completed 7 unit tests, 3 failed in 0m 10s
Configuring Spring Security Core ...
... finished configuring Spring Security Core
| Tests FAILED
| Error Forked Grails VM exited with error

/************************************* AddressControllerSpec ********************************************/



import grails.test.mixin.*
import spock.lang.*

@TestFor(AddressController)
@Mock(Address)
class AddressControllerSpec extends Specification {

def populateValidParams(params) {
assert params != null
// TODO: Populate valid properties like...
//params["name"] = 'someValidName'
}

void "Test the index action returns the correct model"() {

when:"The index action is executed"
controller.index()

then:"The model is correct"
!model.addressInstanceList
model.addressInstanceCount == 0
}

void "Test the create action returns the correct model"() {
when:"The create action is executed"
controller.create()

then:"The model is correctly created"
model.addressInstance!= null
}

void "Test the save action correctly persists an instance"() {

when:"The save action is executed with an invalid instance"
request.contentType = FORM_CONTENT_TYPE
request.method = 'POST'
def address = new Address()
address.validate()
controller.save(address)

then:"The create view is rendered again with the correct model"
model.addressInstance!= null
view == 'create'

when:"The save action is executed with a valid instance"
response.reset()
populateValidParams(params)
address = new Address(params)

controller.save(address)

then:"A redirect is issued to the show action"
response.redirectedUrl == '/address/show/1'
controller.flash.message != null
Address.count() == 1
}

void "Test that the show action returns the correct model"() {
when:"The show action is executed with a null domain"
controller.show(null)

then:"A 404 error is returned"
response.status == 404

when:"A domain instance is passed to the show action"
populateValidParams(params)
def address = new Address(params)
controller.show(address)

then:"A model is populated containing the domain instance"
model.addressInstance == address
}

void "Test that the edit action returns the correct model"() {
when:"The edit action is executed with a null domain"
controller.edit(null)

then:"A 404 error is returned"
response.status == 404

when:"A domain instance is passed to the edit action"
populateValidParams(params)
def address = new Address(params)
controller.edit(address)

then:"A model is populated containing the domain instance"
model.addressInstance == address
}

void "Test the update action performs an update on a valid domain instance"() {
when:"Update is called for a domain instance that doesn't exist"
request.contentType = FORM_CONTENT_TYPE
request.method = 'PUT'
controller.update(null)

then:"A 404 error is returned"
response.redirectedUrl == '/address/index'
flash.message != null


when:"An invalid domain instance is passed to the update action"
response.reset()
def address = new Address()
address.validate()
controller.update(address)

then:"The edit view is rendered again with the invalid instance"
view == 'edit'
model.addressInstance == address

when:"A valid domain instance is passed to the update action"
response.reset()
populateValidParams(params)
address = new Address(params).save(flush: true)
controller.update(address)

then:"A redirect is issues to the show action"
response.redirectedUrl == "/address/show/$address.id"
flash.message != null
}

void "Test that the delete action deletes an instance if it exists"() {
when:"The delete action is called for a null instance"
request.contentType = FORM_CONTENT_TYPE
request.method = 'DELETE'
controller.delete(null)

then:"A 404 is returned"
response.redirectedUrl == '/address/index'
flash.message != null

when:"A domain instance is created"
response.reset()
populateValidParams(params)
def address = new Address(params).save(flush: true)

then:"It exists"
Address.count() == 1

when:"The domain instance is passed to the delete action"
controller.delete(address)

then:"The instance is deleted"
Address.count() == 0
response.redirectedUrl == '/address/index'
flash.message != null
}
}


/******************************** AddressController ******************************************/





import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional

@Transactional(readOnly = true)
class AddressController {

static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]

def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Address.list(params), model:[addressInstanceCount: Address.count()]
}

def show(Address addressInstance) {
respond addressInstance
}

def create() {
respond new Address(params)
}

@Transactional
def save(Address addressInstance) {
if (addressInstance == null) {
notFound()
return
}

if (addressInstance.hasErrors()) {
respond addressInstance.errors, view:'create'
return
}

addressInstance.save flush:true

request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'address.label', default: 'Address'), addressInstance.id])
redirect addressInstance
}
'*' { respond addressInstance, [status: CREATED] }
}
}

def edit(Address addressInstance) {
respond addressInstance
}

@Transactional
def update(Address addressInstance) {
if (addressInstance == null) {
notFound()
return
}

if (addressInstance.hasErrors()) {
respond addressInstance.errors, view:'edit'
return
}

addressInstance.save flush:true

request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'Address.label', default: 'Address'), addressInstance.id])
redirect addressInstance
}
'*'{ respond addressInstance, [status: OK] }
}
}

@Transactional
def delete(Address addressInstance) {

if (addressInstance == null) {
notFound()
return
}

addressInstance.delete flush:true

request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'Address.label', default: 'Address'), addressInstance.id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}

protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'address.label', default: 'Address'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}

更新

这似乎仅在 Intellij 中测试时才会发生。至少...从命令行运行时,7 个测试中只有 3 个失败。以下是命令行运行的结果:

test-app .AddressControllerSpec
| Running 2 unit tests... 3 of 3
| Failure: Test the save action correctly persists an instance(.AddressControllerSpec)
| Condition not satisfied:
model.addressInstance!= null
| | |
[:] null false
at .AddressControllerSpec.Test the save action correctly persists an instance(AddressControllerSpec.groovy:48)
| Running 2 unit tests... 6 of 6
| Failure: Test the update action performs an update on a valid domain instance(.AddressControllerSpec)
| Condition not satisfied:
response.redirectedUrl == '/address/index'
| | |
| null false
org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletResponse@2906a2bf
at .AddressControllerSpec.Test the update action performs an update on a valid domain instance(AddressControllerSpec.groovy:102)
| Running 2 unit tests... 7 of 7
| Failure: Test that the delete action deletes an instance if it exists(.AddressControllerSpec)
| Condition not satisfied:
response.redirectedUrl == '/address/index'
| | |
| null false
org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletResponse@590bd021
at .AddressControllerSpec.Test that the delete action deletes an instance if it exists(AddressControllerSpec.groovy:133)
| Completed 7 unit tests, 3 failed in 0m 6s
Configuring Spring Security Core ...
... finished configuring Spring Security Core
| Tests FAILED

在 Grails 2.4.0 中,我使用“grailsgenerate-all'*'”为我的应用程序生成脚手架。这也会创建 Controller 测试。然而,我相信这些 Controller 测试是错误的。就我而言,每次 7 次测试中有 6 次失败。这是一个损坏的示例:

@TestFor(AddressController)
@Mock(Address)
class AddressControllerSpec extends Specification {
.....
void "Test the create action returns the correct model"() {
when:"The create action is executed"
controller.create()

then:"The model is correctly created"
model.addressInstance != null
}

执行时失败,输出为:

Condition not satisfied:

model.addressInstance != null
| | |
| null false
[address:Address : (unsaved)]

at AddressControllerSpec.Test the create action returns the correct model(AddressControllerSpec.groovy:36)

请注意,模型本身是一个 Address 对象,但 addressInstance 为 null。

查看生成的 AddressController.groovy 中关联的 Controller 操作:

def create() {
respond new Address(params)
}

看看这没有设置一个名为 addressInstance 的变量,这难道不是测试失败的明显原因吗?我是 Grails 的新手(嗯,尝试用它做一些事情的新手),所以我不确定是否有一些本应在这里发挥作用的魔法,但事实并非如此,但事实上该模型确实是在我看来,设置为操作返回的对象表明存在错误。

有人可以在这里检查我的推理吗?我认为这段代码正确吗?

对我来说唯一通过的测试是:“测试索引操作返回正确的模型”

作为引用,这里是完整的 Controller 和测试代码:

import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional

@Transactional(readOnly = true)
class AddressController {

static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]

def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Address.list(params), model:[addressInstanceCount: Address.count()]
}

def show(Address addressInstance) {
respond addressInstance
}

def create() {
respond new Address(params)
}

@Transactional
def save(Address addressInstance) {
if (addressInstance == null) {
notFound()
return
}

if (addressInstance.hasErrors()) {
respond addressInstance.errors, view:'create'
return
}

addressInstance.save flush:true

request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'address.label', default: 'Address'), addressInstance.id])
redirect addressInstance
}
'*' { respond addressInstance, [status: CREATED] }
}
}

def edit(Address addressInstance) {
respond addressInstance
}

@Transactional
def update(Address addressInstance) {
if (addressInstance == null) {
notFound()
return
}

if (addressInstance.hasErrors()) {
respond addressInstance.errors, view:'edit'
return
}

addressInstance.save flush:true

request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'Address.label', default: 'Address'), addressInstance.id])
redirect addressInstance
}
'*'{ respond addressInstance, [status: OK] }
}
}

@Transactional
def delete(Address addressInstance) {

if (addressInstance == null) {
notFound()
return
}

addressInstance.delete flush:true

request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'Address.label', default: 'Address'), addressInstance.id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}

protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'address.label', default: 'Address'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}


/*********************************************************************************/
import grails.test.mixin.*
import spock.lang.*


@TestFor(AddressController)
@Mock(Address)
class AddressControllerSpec extends Specification {
def log = LogFactory.getLog(getClass())
def populateValidParams(params) {
assert params != null
// TODO: Populate valid properties like...
//params["name"] = 'someValidName'
}

void "Test the index action returns the correct model"() {

when:"The index action is executed"

controller.index()

then:"The model is correct"
!model.addressInstanceList
model.addressInstanceCount == 0
}

void "Test the create action returns the correct model"() {
when:"The create action is executed"
controller.create()

then:"The model is correctly created"
model.addressInstance != null
}

void "Test the save action correctly persists an instance"() {

when:"The save action is executed with an invalid instance"
request.contentType = FORM_CONTENT_TYPE
def address = new Address()
address.validate()
controller.save(address)

then:"The create view is rendered again with the correct model"
//model.addressInstance!= null
view == 'create'

when:"The save action is executed with a valid instance"
response.reset()
populateValidParams(params)
address = new Address(params)

controller.save(address)

then:"A redirect is issued to the show action"
response.redirectedUrl == '/address/show/1'
controller.flash.message != null
Address.count() == 1
}

void "Test that the show action returns the correct model"() {
when:"The show action is executed with a null domain"
controller.show(null)

then:"A 404 error is returned"
response.status == 404

when:"A domain instance is passed to the show action"
populateValidParams(params)
def address = new Address(params)
controller.show(address)

then:"A model is populated containing the domain instance"
model.addressInstance == address
}

void "Test that the edit action returns the correct model"() {
when:"The edit action is executed with a null domain"
controller.edit(null)

then:"A 404 error is returned"
response.status == 404

when:"A domain instance is passed to the edit action"
populateValidParams(params)
def address = new Address(params)
controller.edit(address)

then:"A model is populated containing the domain instance"
model.addressInstance == address
}

void "Test the update action performs an update on a valid domain instance"() {
when:"Update is called for a domain instance that doesn't exist"
request.contentType = FORM_CONTENT_TYPE
controller.update(null)

then:"A 404 error is returned"
response.redirectedUrl == '/address/index'
flash.message != null


when:"An invalid domain instance is passed to the update action"
response.reset()
def address = new Address()
address.validate()
controller.update(address)

then:"The edit view is rendered again with the invalid instance"
view == 'edit'
model.addressInstance == address

when:"A valid domain instance is passed to the update action"
response.reset()
populateValidParams(params)
address = new Address(params).save(flush: true)
controller.update(address)

then:"A redirect is issues to the show action"
response.redirectedUrl == "/address/show/$address.id"
flash.message != null
}

void "Test that the delete action deletes an instance if it exists"() {
when:"The delete action is called for a null instance"
request.contentType = FORM_CONTENT_TYPE
controller.delete(null)

then:"A 404 is returned"
response.redirectedUrl == '/address/index'
flash.message != null

when:"A domain instance is created"
response.reset()
populateValidParams(params)
def address = new Address(params).save(flush: true)

then:"It exists"
Address.count() == 1

when:"The domain instance is passed to the delete action"
controller.delete(address)

then:"The instance is deleted"
Address.count() == 0
response.redirectedUrl == '/address/index'
flash.message != null
}
}

最佳答案

测试受 allowedMethods 限制的 Controller 操作时,需要指定请求方法。

参见https://jira.grails.org/browse/GPSCAFFOLD-95

https://jira.grails.org/browse/GRAILS-8426

https://github.com/grails-plugins/grails-scaffolding/commit/db4eed57449e56225821ab565229b76bc394d2be

您可以将 BuildConfig.groovy 中的脚手架插件更新到版本 2.1.1,也可以手动更新生成的测试。

希望对您有所帮助。

关于grails generated-all '*' 创建损坏的 Controller 测试?脚手架生成是否已损坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24071013/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com