Jest.js error: "Received: serializes to the same string"
Solution 1
Similarly to other colleagues I had this issue with an Array comparison, I was basically testing a function that got the largest string in an array, additionally it should return an array if more than 1 of those strings matched the largest length possible.
When I started testing I got the following message:
So I replaced the toBe
method
expect(function(array1)).toBe('one result')
with toStrictEqual
to make a deep equality comparison
expect(function(array2)).toStrictEqual(['more than one', 'more than one']);
Solution 2
I had a similar case where the object had a base64 encoded string, I managed the test to compare the serialization of the object using JSON.stringify
:
expect(JSON.stringify(newDeal)).toMatchObject(JSON.stringify(expected));
Solution 3
Just had this problem when tried to compare arrays where in one array there was an element with -1 index set (imagine any other key to be set except numbers from 0 to N). So you may have this error in the following scenario:
const arr = [1, 2]
arr[-1] = 'foo'
expect(arr).toEqual([1, 2])
They both serialized to the same string, but they are not equal.
Solution 4
I had this problem when i tried to compare arrays where one array was coming back from the Graphql's resolver and the other one was from my test's input.
ALL the fields were the same except the entries inside the array coming from Graphql did not have any __proto__
while the ones from my test input had __proto__: Object
and that cause the toStrictEqual to fail, because it checks the types besides the structure. So, in my case the type caused to fail. Changing it to toEqual
solved the problem.
expect(res.data.myMutation.values).toEqual(
testInput.values,
);
Solution 5
In my situation, I was deep equal checking a proxied object vs a regular object.
const proxyObject = new Proxy({}, {
get: function(target, prop) {
return Object.hasOwnProperty.call(target, prop) ? target[prop] : '';
}
})
expect(proxyObject).toEqual({})
// Expected: {}
// Received: serializes to the same string
It should be:
expect(proxyObject).toMatchObject({})
Jonathan Tuzman
I develop web and desktop applications, primarily with Typescript, React, and Redux. I've also done a good deal of work in React Native, iOS/Swift, WPF/C#, Python (Flask), Ruby on Rails, C++, and certainly others I'm forgetting. Most of my work leans toward front end development, but I really enjoy touching all parts of the stack. What excites me most is working on products that "normal" people (which is to say, not specialists in any given area) use and touch in their everyday lives, that makes their tasks and their passions easier. In my other life, I'm a professional musician, and I fell in love with coding after teaching myself Swift and building an app for audiences at my piano bar gigs. I dove deep into software development, and continue to gobble up new languages and frameworks.
Updated on November 18, 2021Comments
-
Jonathan Tuzman over 2 years
I've having a strange problem with this test:
deal.test.js
import Deal from "../src/models/Deal"; import apiProducts from "../__mocks__/api/products"; describe("Deal", () => { describe("Deal.fromApi", () => { it("takes an api product and returns a Deal", () => { const apiDeal = apiProducts[0]; const newDeal = Deal.fromApi(apiDeal); const expected = expectedDeal(); expect(newDeal).toEqual(expected); }); }); });
Deal.js
export default class Deal { // no constructor since we only ever create a deal from Deal.fromApi static fromApi(obj: Object): Deal { const deal = new Deal(); deal.id = obj.id; deal.name = obj.name; deal.slug = obj.slug; deal.permalink = obj.permalink; deal.dateCreated = obj.date_created; deal.dateModified = obj.date_modified; deal.status = obj.status; deal.featured = obj.featured; deal.catalogVisibility = obj.catalog_visibility; deal.descriptionHTML = obj.description; deal.shortDescriptionHTML = obj.short_description; deal.price = Number(obj.price); deal.regularPrice = Number(obj.regular_price); deal.salePrice = Number(obj.sale_price); deal.dateOnSaleFrom = obj.date_on_sale_from; deal.dateOnSaleTo = obj.date_on_sale_to; deal.onSale = obj.on_sale; deal.purchasable = obj.purchasable; deal.relatedIds = obj.related_ids; deal.upsellIds = obj.upsell_ids; deal.crossSellIds = obj.cross_sell_ids; deal.categories = obj.categories; deal.tags = obj.tags; deal.images = obj.images; return deal; } descriptionWithTextSize(size: number): string { return this.descriptionWithStyle(`font-size:${size}`); } descriptionWithStyle(style: string): string { return `<div style="${style}">${this.description}</div>`; } distanceFromLocation = ( location: Location, unit: unitOfDistance = "mi" ): number => { return distanceBetween(this.location, location); }; distanceFrom = (otherDeal: Deal, unit: unitOfDistance = "mi"): number => { return distanceBetween(this.location, otherDeal.location); }; static toApi(deal: Deal): Object { return { ...deal }; } }
The test fails with this error:
● Deal › Deal.fromApi › takes an api product and returns a Deal expect(received).toEqual(expected) // deep equality Expected: {"catalogVisibility": "visible", "categories": [{"id": 15, "name": "New York", "slug": "new-york"}], "crossSellIds": [34, 31], "dateCreated": "2019-05-18T17:36:14", "dateModified": "2019-05-18T17:39:02", "dateOnSaleFrom": null, "dateOnSaleTo": null, "descriptionHTML": "<p>Pete's Tavern<br /> 129 E 18th St<br /> New York, NY 10003</p> <p>Weekdays from 4 p.m. to 7 p.m.<br /> $5 wines and beers</p> ", "distanceFromLocation": [Function anonymous], "featured": false, "id": 566, "images": [{"alt": "", "date_created": "2019-05-18T17:38:52", "date_created_gmt": "2019-05-18T17:38:52", "date_modified": "2019-05-18T17:38:52", "date_modified_gmt": "2019-05-18T17:38:52", "id": 567, "name": "wine and beers2", "src": "https://tragodeals.com/wp-content/uploads/2019/05/wine-and-beers2.jpg"}], "name": "Wines and beers", "onSale": true, "permalink": "https://tragodeals.com/product/wines-and-beers/", "price": 5, "purchasable": true, "regularPrice": 11, "relatedIds": [552, 564, 390, 37, 543], "salePrice": 5, "shortDescriptionHTML": "<p>$5 wines and beers</p> ", "slug": "wines-and-beers", "status": "publish", "tags": [{"id": 58, "name": "beers", "slug": "beers"}, {"id": 54, "name": "Cocktails", "slug": "cocktails"}, {"id": 45, "name": "drink", "slug": "drink"}, {"id": 57, "name": "wine", "slug": "wine"}], "upsellIds": [53]} Received: serializes to the same string > 15 | expect(newDeal).toEqual(expected); | ^ 16 | }); 17 | }); 18 | }); at Object.toEqual (__tests__/deal.test.js:15:23)
I inserted this loop to investigate:
for (let key in expected) { expect(expected[key]).toEqual(newDeal[key]); }
And I see that the problem is with functions. So I changed the whole test to this:
for (let key in expected) { if (typeof expected[key] === "function") continue; expect(expected[key]).toEqual(newDeal[key]); } // expect(newDeal).toEqual(expected);
And it passes, and also fails when it should. (if you read the old version of this question where I was getting passing tests that I didn't understand, it was because I was
return
ing from the loop when I should have beencontinue
ing).But I'd like to be able to do it with the standard assertion
expect(newDeal).toEqual(expected)
. It looks like there's something I'm not understanding about checking for class object (Deal
) equality with functions.PS. You might suggest using
toMatchObject
. But, sadly:● Deal › Deal.fromApi › takes an api product and returns a Deal expect(received).toMatchObject(expected) - Expected + Received @@ -1,6 +1,6 @@ - Deal { + Object { "address": "129 E 18th St New York, NY 10003", "catalogVisibility": "visible", "categories": Array [ Object { "id": 15, 13 | expect(expected[key]).toEqual(newDeal[key]); 14 | } > 15 | expect(newDeal).toMatchObject(expected); | ^ 16 | }); 17 | }); 18 | });
-
gonzofish about 3 yearsMy problem was that we'd put a static property on our array, which is similar to this
-
ACV over 2 years
expect(newDeal).toMatchObject(expected)
will do. No need to convert to string. -
Jose Quijada over 2 years@AVC Are you sure that's correct? Jest says this about
expect(newDeal).toMatchObject(expected)
:It will match received objects with properties that are not in the expected object.
. It did not work for me when I tried it. I had to doJSON.stringify()
on both sides of the equation in order for thetoEqual()
comparison to succeed. -
Muhaimin Taib almost 2 yearsusing
toEqual
will also works, in conclusion, do not usetoBe
to compare arrays. -
Mario Perez almost 2 yearsBack when I posted I think the toEqueal method didn’t cut it, I’ll have a look at it