47

So when testing one of my reducers in a Preact(not much different to React while testing with JEST) based project, I got bumped into this issue:

Following output comes up when running jest test -

● 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",
    +   },
      }

Following is the test case:

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),
    })

})

Since state gets changed while calling that reducer, I needed to use expect.any function, but as per the output, although types are same, test is not getting passed. Rather in expected its showing up Any<String>.

rupav jain
  • 645
  • 1
  • 7
  • 13

2 Answers2

56

expect.toEqual checks for equality of state.active in your case. To achieve what you want, you have to make multiple expect statements:

expect(state.active.active).toEqual(true)
expect(state.active.data).toEqual(expect.any(Array))
expect(state.active.ID).toEqual(expect.any(String))
Adam Azad
  • 11,171
  • 5
  • 29
  • 70
lipp
  • 5,586
  • 1
  • 21
  • 32
  • 2
    thanks for the quick response, but what I really want to achieve is basically use `any` for only things which are inevitable to change, here say "ID". Consider this, my Reducer returns a state which is an object say, **Z** = { ID: 'hdgajs35', X:'fixed_data1', Y: 'fixed_data2' }. Now with your approach I can only check if ID is of String type. I would never be able to check X,Y, and similarly many other fields in the state object. What I plan to do is this: expect(state).toEqual({ ID: expect.any(String), ...fixed_state }) where fixed_state is **Z** but with different ID. – rupav jain Jun 04 '18 at 12:24
  • Sorry, I did not get your point. maybe you can add what you want to expect in the test more verbosely or with pseudo-code. Anyhow: expect(state).toEqual most likely won't be your friend, since this matches object equality which will only pass if you have the very same object. Maybe expect(state).toMatchObject can help you – lipp Jun 04 '18 at 13:41
  • tried .toMatchObject, was working great. But later on, I found that It was fault in my logic. Now .any is working inside expect().toEqual(). ✨ Thank you so much for your time. Much appreciated. Happy its working successfully – rupav jain Jun 04 '18 at 18:31
  • happy to help. does your code from the question work with .toMatchObject instead of .toEqual? – lipp Jun 04 '18 at 20:16
  • Yup with .toMatchObject worked, as stated in the docs toMatchObject just matches all the subsets, since I had a fault in logic for this test case, I was comparing wrong objects altogether, now I had to dump above code, and make new test case with expect.any for correct logic. – rupav jain Jun 05 '18 at 03:38
33

You can use toMatchObject:

expect(state.active).toMatchObject({
    active: true,
    data: expect.any(Array),
    ID: expect.any(String)
});

See more examples in official documentation: https://jestjs.io/docs/en/expect#tomatchobjectobject

Ilarion Halushka
  • 2,083
  • 18
  • 13