开玩笑的自定义匹配器

时间:2017-08-17 19:29:56

标签: javascript jestjs

我试图在Jest中创建一个类似于stringMatching的自定义匹配器,但它接受空值。但是,文档并未显示如何重用现有匹配器。到目前为止,我有这样的事情:

expect.extend({
    stringMatchingOrNull(received, argument) {
        if (received === null) {
            return {
                pass: true,
                message: () => 'String expected to be null.'
            };
        }

        expect(received).stringMatching(argument);
    }
});

我不确定这是否正确,因为我在调用stringMatching匹配器时没有返回任何内容(建议使用here)。当我尝试使用这个匹配器时,我得到:expect.stringMatchingOrNull is not a function,即使在相同的测试用例中声明了这一点:

expect(player).toMatchObject({
    playerName: expect.any(String),
    rank: expect.stringMatchingOrNull(/^[AD]$/i)
    [...]
});

拜托,有人可以帮我展示正确的方法吗?

我使用Jest 20.0.4和Node.js 7.8.0运行测试。

2 个答案:

答案 0 :(得分:10)

有两种与expect相关的不同方法。当您致电expect(value)时,您会获得一个带有 matchers 方法的对象,您可以将这些方法用于各种断言(例如toBe(value)toMatchSnapshot())。另一种方法直接在expect上,它们基本上是辅助方法(expect.extend(matchers)就是其中之一)。

使用expect.extend(matchers)添加第一种方法。这意味着它不能直接在expect上获得,因此您得到的错误。您需要按如下方式调用它:

expect(string).stringMatchingOrNull(regexp);

但是当你打电话给你时,你会得到另一个错误。

TypeError: expect(...).stringMatching is not a function

这次你尝试使用use expect.stringMatching(regexp)作为匹配器,但它是expect上的辅助方法之一,它为你提供了一个伪值,可以被接受为任何与正则表达式匹配的字符串值。这允许你像这样使用它:

expect(received).toEqual(expect.stringMatching(argument));
//     ^^^^^^^^          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//      string                   acts as a string

这个断言只会在失败时抛出,这意味着当它成功时函数继续并且不会返回任何内容(undefined)并且Jest会抱怨你必须返回一个{{1}的对象和可选的pass

message

您需要考虑的最后一件事是在匹配器之前使用.not。使用Unexpected return from a matcher function. Matcher functions should return an object in the following format: {message?: string | function, pass: boolean} 'undefined' was returned 时,您还需要在自定义匹配器中进行的断言中使用.not,否则在应该通过时会失败。幸运的是,这很简单,因为您可以访问.not

this.isNot

请注意,expect.extend({ stringMatchingOrNull(received, regexp) { if (received === null) { return { pass: true, message: () => 'String expected to be not null.' }; } // `this.isNot` indicates whether the assertion was inverted with `.not` // which needs to be respected, otherwise it fails incorrectly. if (this.isNot) { expect(received).not.toEqual(expect.stringMatching(regexp)); } else { expect(received).toEqual(expect.stringMatching(regexp)); } // This point is reached when the above assertion was successful. // The test should therefore always pass, that means it needs to be // `true` when used normally, and `false` when `.not` was used. return { pass: !this.isNot } } }); 仅在断言未产生正确结果时显示,因此最后message不需要消息,因为它将始终通过。错误消息只能在上面发生。您可以通过running this example on repl.it查看所有可能的测试用例和生成的错误消息。

答案 1 :(得分:0)

我写了这个hack来使用////# declare globally (not inside some specific function..) //var destDim :Point = new Point(your_X_num , your_Y_num); //var bgColor :uint = 0x505050; var bm:BitmapData = new BitmapData(destDim.x, destDim.y, true, bgColor); var result:Bitmap = new Bitmap(bm, PixelSnapping.NEVER, true); //result.bitmapData = bm; //can be set here but done within function for clarity... var mtx:Matrix = new Matrix(); ////# update bitmap by replacing its bitmapdata with new colour values of existing pixels function Here_is_my_loop (): void { trace('before drawing :'+(System.privateMemory/1024)); //overwrite pixel colours in bitmap (result) bm.draw(myBigSprite, mtx, null, null, null, true); result.bitmapData = bm; //update bitmap trace('after drawing :'+(System.privateMemory/1024)); //return result and encode Bitmap to png //result.bitmapData.dispose(); //result.bitmapData = null; //result = null; } 中的任何.to...函数,包括添加了.toEqual的自定义函数。

expect.extend

...

class SatisfiesMatcher {
  constructor(matcher, ...matcherArgs) {
    this.matcher = matcher
    this.matcherArgs = matcherArgs
  }
  asymmetricMatch(other) {
    expect(other)[this.matcher](...this.matcherArgs)
    return true
  }
}
expect.expect = (...args) => new SatisfiesMatcher(...args)