我想扩展Jest的isEqual
匹配器,以便在比较之前转换期望值(这允许我在测试中使用多行字符串)。我需要做的就是通过lib indentToFirstLine
中的indent-to-first-line
函数运行期望值,然后再将其传递给isEqual
。显然,我并不想在任何需要的地方都这样做,所以将它折叠成匹配器是有意义的,因为我想要与Jest / Expect的isEqual
匹配器具有相同的功能,利用它是有道理的。
我尝试过以下方法:
import indentToFirstLine from 'indent-to-first-line'
import expect from 'expect'
const toEqualMultiline = (received, expectedTemplateString) => {
const expected = indentToFirstLine(expectedTemplateString)
return expect(received).toEqual(expected)
}
export default toEqualMultiline
但是expect(received).toEqual(expected)
没有返回值,因此我的匹配器在undefined
中返回的值导致Jest错误:
来自匹配器功能的意外返回。 匹配器函数应以以下格式返回对象: {message?:string | function,pass:boolean} '未定义'被退回
我是否可以在自己的匹配器中使用toEqual
?
答案 0 :(得分:1)
如果您正在使用玩笑并将匹配器传递给 expect.extend ,则可以使用提供的执行上下文来执行玩笑的 equals 方法,如下所示:< / p>
import indentToFirstLine from 'indent-to-first-line'
export default function toEqualMultiline(received, expectedTemplateString) {
const expected = indentToFirstLine(expectedTemplateString);
return {
message: () => `expected ${received} to equals multiline ${expected}`,
pass: this.equals(received, expected)
};
}
答案 1 :(得分:1)
您可以使用expect.extend()
来做到这一点。如果您使用的是create-react-app,则可以将此示例代码放在setupTests.ts
下方,以便将其应用于您运行的所有测试:
expect.extend({
toBeWithinRange(received, min, max) {
const pass = received >= min && received <= ceiling
return {
message: () =>
`expected ${received} to be in range ${floor} - ${ceiling}`,
pass,
}
},
})
it('should fail', () => {
expect(13).toBeWithinRange(1, 10)
})
运行上面的测试时,输出为:
但是我们可以做得更好。查看内置匹配器如何显示错误消息:
如您所见,该错误更容易阅读,因为期望和已接收值具有不同的颜色,并且上面有一个匹配提示来指示哪个是哪个。
为此,我们需要安装此软件包jest-matcher-utils
,并导入一些方法以漂亮地显示匹配器提示和值:
import { printExpected, printReceived, matcherHint } from "jest-matcher-utils"
const failMessage = (received, min, max) => () => `${matcherHint(
".toBeWithinRange",
"received",
"min, max"
)}
Expected value to be in range:
min: ${printExpected(min)}
max: ${printExpected(max)}
Received: ${printReceived(received)}`
expect.extend({
toBeWithinRange(received, min, max) {
const pass = received >= min && received <= max
return {
pass,
message: failMessage(received, min, max),
}
},
})
现在看起来更好,可以帮助您更快地发现问题
但是,当您否定断言时,上面的代码中有一个小错误
expect(3).not.toBeWithinRange(1, 10)
输出为.toBeWithinRange
而不是.not.toBeWithinRange
:
expect(received).toBeWithinRange(min, max)
Expected value to be in range:
min: 1
max: 10
Received: 3
要解决此问题,您可以根据pass
值有条件地添加否定词
const failMessage = (received, min, max, not) => () => `${matcherHint(
`${not ? ".not" : ""}.toBeWithinRange`,
"received",
"min, max"
)}
Expected value${not ? " not " : " "}to be in range:
min: ${printExpected(min)}
max: ${printExpected(max)}
Received: ${printReceived(received)}`
toBeWithinRange(received, min, max) {
const pass = received >= min && received <= max
return {
pass,
message: failMessage(received, min, max, pass),
}
},
现在再次重新运行测试,您将看到:
通过false
expect(3).not.toBeWithinRange(1, 10)
expect(received).not.toBeWithinRange(min, max)
Expected value not to be in range:
min: 1
max: 10
Received: 3
通过true
expect(13).toBeWithinRange(1, 10)
expect(received).toBeWithinRange(min, max)
Expected value to be in range:
min: 1
max: 10
Received: 13