2

我正在 Grails 中编写一个测试,以确保来自客户端的传入 JSON 包含所有必需的字段。地图看起来像:

def map = [
    customer: [
        firstName: 'John',
        lastName: 'Doe',
        id: '123',
    ],
    orderNumber: '123456',
    paymentInfo: [
        type: 'paypal',
        amount: '1200',
        currency: 'USD'
    ]
]

所以换句话说,customerpaymentInfo键是映射本身与子键。

在我的测试中,我想删除每个键和子键以确保输入验证正常工作。我做了这样的事情:

// test 1
map.remove('orderNumber')
def result = service.performAction(map)
assert result == ServiceCall.ValidationError

// test 2
map.remove('customer.firstName')
def result = service.performAction(map)
assert result == ServiceCall.ValidationError

测试 1 正常工作并正确删除了orderNumber密钥,但测试 2 没有删除firstName子密钥。我知道我可以使用map.customer.remove(firstName)它并且它会正确删除子键,但是我试图使测试足够通用,以便我只需要传入一个字符串数组,它们的键和子键将被正确删除,例如:

def array = ['orderNumber', 'customer.firstName', 'customer.lastName', etc...]

array.each {
    map.remove(it)
    def result = service.performAction(map)
    assert result == ServiceCall.ValidationError
}

是否可以通过这种方式删除子项,如果可以,我该怎么做?

4

1 回答 1

2

不幸的是,'customer.firstName' 不是顶级地图的键,所以它不起作用。相反,您可以做一些事情来解析您传入的键。

试试这个?

array.each {
   def levels = it.tokenize('.')
   if ( levels.size() == 1 ) {
      map.remove(levels[0])
   } else if ( level.size() == 2 ) {
      map.get(levels[0]).remove(levels[1])
   } // else etc.
   def result = service.performAction(map)
   assert result == ServiceCall.ValidationError
}

请注意,我在深度方面做了这个非常非通用的......您可以轻松编写一个通用函数来删除第 n 级地图属性。但是如果你知道你只需要深入 2 甚至 3 层,那么这样的事情应该可以正常工作,而无需一堆难以阅读的通用代码。

如果您绝对想让它适用于任意深度的子地图,请执行以下操作:

array.each {
   def levels = it.tokenize('.')
   if ( levels.size() == 1 ) {
      map.remove(levels[0])
   } else  {
      def ref = map
      levels[0..-2].each {
          ref = ref[it]
      }
      ref.remove(levels[-1])
   }
   def result = service.performAction(map)
   assert result == ServiceCall.ValidationError
}

我确实注意到您的“地图”在测试之间没有恢复......您的原始测试也没有这样做,所以我的代码表现相同。

于 2013-03-12T03:22:20.337 回答