Jest中的expect.any()无法正常工作。

49

在一个基于Preact(与使用JEST测试React几乎没有太大区别)的项目中测试我的一个reducers时,我遇到了这个问题:

运行jest测试时会出现以下输出 -

● should setup 

    expect(received).toEqual(expected)

    Expected value to equal:
      {"ID": Any<String>, "active": true, "data": Any<Array>}
    Received:
      {"ID": "BysnEuMlm", "active": true, "data": [{"ID": "Hy7wMAz1lm", "code": "dat.fle", "label": "CRES/datum14.cdata", "name": "File", "status": "READY", "value": {"format": "cdata", "name": "datum14.cdata", "path": "CRES"}}, {"ID": "rkB7RMkeX", "code": "prp.kcv", "label": "3 folds", "name": "k-Fold Cross-Validation", "status": "READY", "value": "3"}, {"ID": "ByCmRfygQ", "code": "ats", "label": undefined, "name": " Best First +  Cfs Subset Eval", "status": "READY", "value": {"evaluator": {"name": "CfsSubsetEval"}, "search": {"name": "BestFirst", "options": ["-D", "1", "-N", "5"]}, "use": true}}, {"ID": "HkmVAM1l7", "code": "lrn", "label": undefined, "name": "Naive Bayes", "status": "READY", "value": {"label": "Naive Bayes", "name": "bayes.NaiveBayes", "use": true}}], "output": {"format": "pipeline", "name": "jestReact.cpipe", "path": "/home/rupav/opensource/candis/CRES"}}

    Difference:

    - Expected
    + Received

      Object {
    -   "ID": Any<String>,
    +   "ID": "BysnEuMlm",
        "active": true,
    -   "data": Any<Array>,
    +   "data": Array [
    +     Object {
    +       "ID": "Hy7wMAz1lm",
    +       "code": "dat.fle",
    +       "label": "CRES/datum14.cdata",
    +       "name": "File",
    +       "status": "READY",
    +       "value": Object {
    +         "format": "cdata",
    +         "name": "datum14.cdata",
    +         "path": "CRES",
    +       },
    +     },
    +     Object {
    +       "ID": "rkB7RMkeX",
    +       "code": "prp.kcv",
    +       "label": "3 folds",
    +       "name": "k-Fold Cross-Validation",
    +       "status": "READY",
    +       "value": "3",
    +     },
    +     Object {
    +       "ID": "ByCmRfygQ",
    +       "code": "ats",
    +       "label": undefined,
    +       "name": " Best First +  Cfs Subset Eval",
    +       "status": "READY",
    +       "value": Object {
    +         "evaluator": Object {
    +           "name": "CfsSubsetEval",
    +         },
    +         "search": Object {
    +           "name": "BestFirst",
    +           "options": Array [
    +             "-D",
    +             "1",
    +             "-N",
    +             "5",
    +           ],
    +         },
    +         "use": true,
    +       },
    +     },
    +     Object {
    +       "ID": "HkmVAM1l7",
    +       "code": "lrn",
    +       "label": undefined,
    +       "name": "Naive Bayes",
    +       "status": "READY",
    +       "value": Object {
    +         "label": "Naive Bayes",
    +         "name": "bayes.NaiveBayes",
    +         "use": true,
    +       },
    +     },
    +   ],
    +   "output": Object {
    +     "format": "pipeline",
    +     "name": "jestReact.cpipe",
    +     "path": "/home/rupav/opensource/candis/CRES",
    +   },
      }

以下是测试用例:

test('should setup ', () => {
    const state = documentProcessor(
        undefined,
        {
            type: ActionType.Asynchronous.READ_SUCCESS,
            payload: dokuments.active
    })
    // expect(state.active.ID).toEqual(expect.any(String)) - Test case passes iff I run this test with this command only.
    expect(state.active).toEqual({
        data: expect.any(Array),
        active: true,
        ID: expect.any(String),
    })

})

由于在调用那个 reducer 时状态会发生改变,所以我需要使用 expect.any 函数,但是根据输出,尽管类型相同,测试未通过。 相反,在期望中显示的是 Any<String>

2个回答

60

expect.toEqual 检查你的情况下 state.active 是否相等。要达到你想要的效果,你需要做多个 expect 语句:

expect(state.active.active).toEqual(true)
expect(state.active.data).toEqual(expect.any(Array))
expect(state.active.ID).toEqual(expect.any(String))

2
谢谢您的快速回复,但我真正想要实现的是仅对不可避免更改的内容使用 any,比如说 "ID"。请考虑以下情况,我的 Reducer 返回一个状态对象,例如 Z = { ID: 'hdgajs35',X:'fixed_data1',Y:'fixed_data2'}。 现在,使用您的方法,我只能检查 ID 是否为字符串类型。我将无法检查 X、Y 和许多其他状态对象中的字段。我的计划是这样的: expect(state).toEqual({ ID: expect.any(String), ...fixed_state })其中 fixed_state 是 Z,但 ID 不同。 - rupav jain
抱歉,我没有理解你的意思。也许你可以更详细地或用伪代码添加你想要在测试中期望的内容。无论如何:expect(state).toEqual很可能不会是你的朋友,因为它匹配对象相等性,只有当你拥有完全相同的对象时才会通过。也许expect(state).toMatchObject可以帮助你。 - lipp
尝试使用 .toMatchObject,一开始运行得很好。 但后来发现是我的逻辑有误。 现在在 expect().toEqual() 中使用 .any 已经可以正常工作了。✨ 非常感谢您的时间。非常感激。 很高兴它已经成功地运行了。 - rupav jain
很高兴能帮忙。你在问题中的代码使用 .toEqual 代替 .toMatchObject 行不行? - lipp
Yup与.toMatchObject一起使用,正如文档中所述,toMatchObject只匹配所有子集, 由于我在这个测试用例的逻辑上有一个错误,我完全比较了错误的对象,现在我不得不放弃上面的代码,并创建新的测试用例以获得正确的逻辑,使用expect.any。 - rupav jain

36

1
这个答案更容易阅读。 - mikemaccana
1
哇塞!像魔法一样运行良好。 - ChrisRich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接