我想写一个测试,Assert一个给定的对象 * 没有 * 某些属性。
假设我有一个函数
function removeFooAndBar(input) {
delete input.foo;
delete input.bar;
return input;
}
现在我要写一个测试:
describe('removeFooAndBar', () => {
it('removes properties `foo` and `bar`', () => {
const data = {
foo: 'Foo',
bar: 'Bar',
baz: 'Baz',
};
expect(removeFooAndBar(data))
.toEqual(expect.objectContaining({
baz: 'Baz', // what's left
foo: expect.not.exists() // pseudo
bar: undefined // this doesn't work, and not what I want
}));
});
});
正确的方式是什么?
7条答案
按热度按时间3lxsmp7m1#
Update after the discussion in the comments
You can use
expect.not.objectContaining()
. This approach works fine but has one unfortunate edge case: It matches when the property exists, but isundefined
ornull
. To fix this you can explicitly add those values to be included in the check. You need thejest-extended
package for thetoBeOneOf()
matcher.An example with nested props that fails:
Original answer
What I'd do is to explicitly check whether the object has a property named
bar
orfoo
.Or make this less repeating by looping over the properties that will be removed.
However, the loop approach isn't too great for possible nested objects. I believe what you are looking for is
expect.not.objectContaining()
expect.not.objectContaining(object)
matches any received object that does not recursively match the expected properties. That is, the expected object is not a subset of the received object. Therefore, it matches a received object which contains properties that are not in the expected object. - Jest Documentationhgncfbus2#
您可以明确检查对象是否具有名为
bar
或foo
的属性。对于嵌套属性:
或者,通过循环访问将要删除的属性,减少重复性。
然而,循环方法对于可能的嵌套对象来说并不太好。
这种方法工作正常,但有一个不幸的边缘情况:当属性存在但为
undefined
或null
时,它会相符:要解决这个问题,您可以显式地添加这些值,使其包含在检查中。您需要
toBeOneOf()
匹配器的jest-extended
包。下面是一个包含嵌套 prop 的示例,该示例在预期中会失败:
0h4hbjxa3#
你能检查一下结果吗?
您可以首先检查属性是否存在。
The other option is to extend the expect function: https://jestjs.io/docs/expect#expectextendmatchers
uurity8g4#
我只想试试:
6l7fqoea5#
我会尝试,因为您知道使用它的
data
值:**编辑1:**由于Jest的
expect.not
,请尝试以下内容:gtlvzcf86#
不要像其他人建议的那样选中
object.foo === undefined
。如果对象的属性foo
设置为undefined
,则结果为true例如
您是否尝试过使用hasOwnProperty函数?
这将为您提供以下结果
bf1o4zei7#
It is possible to check whether an object has selected fields (
expect.objectContaining
) and in a separate assertion whether it does not have selected fields (expect.not.objectContaining
). However, it is not possible, by default, to check these two things in one assertion, at least I have not heard of it yet.Goal: create a
expect.missing
matcher similar to standardexpect.any
orexpect.anything
which will check if the object does not have the selected field and can be used alongside matchers of existing fields.My attempts to reach this goal are summarized below, maybe someone will find them useful or be able to improve upon them. I point out that this is a proof of concept and it is possible that there are many errors and cases that I did not anticipate.
AsymmetricMatchers in their current form lack the ability to check their context, for example, when checking the
expect.any
condition fora
in the object{ a: expect.any(String), b: [] }
,expect.any
knows nothing about the existence ofb
, the object in whicha
is a field or even that the expected value is assigned to the keya
. For this reason, it is not enough to create onlyexpect.missing
but also a custom version ofexpect.objectContaining
, which will be able to provide the context for ourexpect.missing
matcher.expect.missing
draft:Somehow the matcher above should be given context: object and property name. We will create a custom
expect.objectContaining
- let's call itexpect.objectContainingOrNot
:Register new matchers to the
expect
:Full complete code:
Usage examples:
When we assume that the field is also missing when it equals undefined (
{ a: undefined }
=>a
is missing) then the need to pass the context toexpect.missing
disappears and the above code can be simplified to:It was fun, have a nice day!