我在 Spock 上遇到了问题,在比较相同的字符串时出现断言错误。
我的测试用例:
def "should return error when email already exists in company"() {
given: "A register driver request"
def requestBody = [
driverId: 12345L,
companyId: "company123",
email: "[email protected]",
isActive: true
]
def email = requestBody.email
def companyId = requestBody.companyId
and: "Insert a driver with the same email into the database"
driverRepository.save(DriverEntity.builder()
.id("uniqueId1")
.companyId(companyId)
.driverId("67890")
.email(email)
.build())
when: "The register driver endpoint is called"
def response = webTestClient.post()
.uri("/drivers")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.bodyValue(requestBody)
.exchange()
then: "The response indicates a bad request due to duplicate email"
response.expectStatus().isEqualTo(422)
.expectBody()
.jsonPath("\$.error").isEqualTo("EMAIL_ALREADY_EXISTS")
.jsonPath("\$.description").isEqualTo("Email [${email}] already exists in company [${companyId}]")
}
但是字符串是相同的:
Expected :Email [[email protected]] already exists in company [company123]
Actual :Email [[email protected]] already exists in company [company123]
当我在断言中使用字符串文字时,没有
${}
占位符,如下所示:
"Driver ID [12345] already exists in company [company123]"
效果很好。
这个问题有解决办法吗?
无论
isEqualTo
来自何处,它可能没有像 Groovy 本身那样对 Groovy GString
进行特殊处理。
例如,如果您检查此脚本:
def txt = 'a'
assert 'a' == "$txt"
assert !'a'.equals("$txt")
assert 'a'.equals("$txt" as String)
然后您会看到,对于 Groovy,
String
和 GString
是相等的。equals
,那么它们就不一样了。isEqualTo
正在测试什么。
因此,如果您只是在
as String
之后添加 GString
,它应该尽早解析占位符并使其成为正常的 String
,从而通过比较。
只要您的
GString
中没有任何占位符,即使您使用双引号,它实际上也会被编译为常规 String
。
但我更喜欢始终使用单引号,如果我不想进行任何替换,则明确将其设为 String
。这还可以提高编译速度,因为不必检查 GString
是否包含占位符,而可以简单地按字面意思理解。
在 Groovy 中还有更多表达字符串的方法,例如
/foo\bar/
,其中反斜杠不是转义字符。如果您包含占位符,这又是一个 GString
。有关更多信息,请参阅 https://groovy-lang.org/syntax.html#all-strings。