grails:代码中 list.contains 的行为与集成测试
想象一下,有一个表单可以对一组登录名及其状态进行批量更新;使用的逻辑是有一个隐藏字段,用于跟踪所有可能的 id 和一组……例如无线电 btns。稍后通过服务,激活列表中所有已检查的 ID 并停用其余部分:
def enabledLogins = toList(params.enabledLogins)
def allLoginIds = params.allLoginIds.toString().split(',')
loginService.updateLoginStatus(allLoginIds,enabledLogins)
这是服务的定义
def updateLoginStatus(String[] allLoginIds, List<Long> enabledLoginIds) {
for (item in allLoginIds) {
def login = Login.get(item.toLong())
if (login) {
login.enabled = enabledLoginIds.contains(item.toLong()) ? true : false
login.save()
if (login.hasErrors()) {
login.errors.each { log.error(it) }
}
}
}
}
这是集成测试:
def testUpdateLoginStatus() {
def id1 = createLogin().id
def id2 = createLogin().id
String[] allLoginIds = [id1 as String, id2 as String]
List<Long> enabledLoginIds = [id1]
loginService.updateLoginStatus(allLoginIds, enabledLoginIds)
def login1 = Login.get(id1)
def login2 = Login.get(id2)
assertTrue login1.enabled
assertFalse login2.enabled
}
Login createLogin() {
def now = System.currentTimeMillis()
def email = "int-test-" + now + "@somewhere.com"
def password = "Pwd" + now + "pwD"
def login = new Login(username: email, password: password, firstName: "Integration", lastName: "Test")
login.save(flush: true)
assertNotNull login.id
return login
}
现在问题是:
上面的代码只是通过了集成测试,但在实践中不起作用,除非我将 toLong 从
enabledLoginIds.contains(item.toLong())which in that case integration test fails... so the type somewhere somehow, is wrong... but I cannot see it
thanks
Ps: grails 1.3.7
Imagine there is a form to do a bulk update for a group of logins and their statuses; the logic used is about having a hidden field which keeps track of all possible ids and a group of… e.g. radio btns. later thru a service, activating whatever checked ids in our list and deactivating rest:
def enabledLogins = toList(params.enabledLogins)
def allLoginIds = params.allLoginIds.toString().split(',')
loginService.updateLoginStatus(allLoginIds,enabledLogins)
here is the definition for the service
def updateLoginStatus(String[] allLoginIds, List<Long> enabledLoginIds) {
for (item in allLoginIds) {
def login = Login.get(item.toLong())
if (login) {
login.enabled = enabledLoginIds.contains(item.toLong()) ? true : false
login.save()
if (login.hasErrors()) {
login.errors.each { log.error(it) }
}
}
}
}
And here is the integration test:
def testUpdateLoginStatus() {
def id1 = createLogin().id
def id2 = createLogin().id
String[] allLoginIds = [id1 as String, id2 as String]
List<Long> enabledLoginIds = [id1]
loginService.updateLoginStatus(allLoginIds, enabledLoginIds)
def login1 = Login.get(id1)
def login2 = Login.get(id2)
assertTrue login1.enabled
assertFalse login2.enabled
}
Login createLogin() {
def now = System.currentTimeMillis()
def email = "int-test-" + now + "@somewhere.com"
def password = "Pwd" + now + "pwD"
def login = new Login(username: email, password: password, firstName: "Integration", lastName: "Test")
login.save(flush: true)
assertNotNull login.id
return login
}
now here is the problem:
The code above just passes integration test but not working in practice unless I take the toLong out of the
enabledLoginIds.contains(item.toLong())
which in that case integration test fails...
so the type somewhere somehow, is wrong... but I cannot see it
thanks
Ps: grails 1.3.7
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
所有参数都以字符串形式出现,因此控制器中的代码是:
这是创建字符串列表。这就是为什么如果您在运行应用程序时取出 .toLong() ,它就会起作用。因为它正在做:
而不是你当前使用 .toLong 的实现,这会导致:
我在这里看到了一些事情:
1)记住泛型只是编译时的(所以在 groovy 中基本上毫无价值)。因此,即使您的方法签名中有一个参数
(... , ListenabledLoginIds)
。在运行时,不能保证它将是一个长整型列表。2)我通常通过控制器进行集成测试。这可以为您提供更好的端到端测试,并有助于避免此类问题。它通过了测试,但在生产中不起作用,因此您认为测试有问题。
All parameters come across as Strings so the code in your Controller is:
Which is creating a list of Strings. This is why if you take out the .toLong() when you're running the app it works. Because then it is doing:
Instead of your current implementation with the .toLong which would result in:
There are a couple of things that I see here:
1) Remember that generics are compile time only (so basically worthless in groovy). So even though you have a parameter of
(... , List<Long> enabledLoginIds)
in your method signature. At runtime there is no guarantee that it will be a List of Longs.2) I usually integration test through the controller. This give you a little better end to end test and helps to avoid problems like this. Where it passes the test, but doesn't work in production so then you think there's something wrong with the test.