grails:代码中 list.contains 的行为与集成测试

发布于 2024-12-28 00:11:06 字数 1796 浏览 2 评论 0原文

想象一下,有一个表单可以对一组登录名及其状态进行批量更新;使用的逻辑是有一个隐藏字段,用于跟踪所有可能的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清晰传感 2025-01-04 00:11:06

所有参数都以字符串形式出现,因此控制器中的代码是:

def enabledLogins = toList(params.enabledLogins)

这是创建字符串列表。这就是为什么如果您在运行应用程序时取出 .toLong() ,它就会起作用。因为它正在做:

["1", "2"].contains("1")

而不是你当前使用 .toLong 的实现,这会导致:

["1", "2"].contains(1)

我在这里看到了一些事情:

1)记住泛型只是编译时的(所以在 groovy 中基本上毫无价值)。因此,即使您的方法签名中有一个参数 (... , ListenabledLoginIds) 。在运行时,不能保证它将是一个长整型列表。

2)我通常通过控制器进行集成测试。这可以为您提供更好的端到端测试,并有助于避免此类问题。它通过了测试,但在生产中不起作用,因此您认为测试有问题。

All parameters come across as Strings so the code in your Controller is:

def enabledLogins = toList(params.enabledLogins)

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:

["1", "2"].contains("1")

Instead of your current implementation with the .toLong which would result in:

["1", "2"].contains(1)

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文