-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Received: serializes to the same string" on object equality checking #8475
Comments
@sabriele Yes, your choice of
|
@sabriele From reading Jest code and guessing about MongoDB, Here is a work-around to get rid of them: expect([...users]).toMatchObject(expectedUsers) If you can paste the received |
I have the same issue. Here is the test for a react custom hook: import {renderHook} from 'react-hooks-testing-library'
import useTheme, {DEFAULT_THEME} from 'components/globalStyle/useTheme'
it('should set the global theme', () => {
const setTheme = () => {}
const expected = {...DEFAULT_THEME, setTheme}
const {result} = renderHook(useTheme)
expect(result.current).toMatchObject(expected)
}) This test returns the following error:
I tried the shallow copy trick that @pedrottimark suggested but it didn't work (same error). However, the following seems to work just fine: import {renderHook} from 'react-hooks-testing-library'
import useTheme, {DEFAULT_THEME} from 'components/globalStyle/useTheme'
it('should set the global theme', () => {
const Mock = jest.fn()
const setTheme = new Mock()
const {result} = renderHook(useTheme)
const expected = {...DEFAULT_THEME, setTheme}
expect(result.current).toMatchObject(expected)
}) Setting Error: expect(received).toMatchObject(expected)
- Expected
+ Received
Object {
"palette": "dark",
- "setTheme": [Function mockConstructor],
+ "setTheme": [Function setTheme],
"textSize": "normal",
} |
@matchatype If the problem in your #8475 (comment) is like #8166 that deep-equality matchers compare functions according to referential identity, then we recommend asymmetric matcher as expected value, see https://jestjs.io/docs/en/expect#expectanyconstructor it('should set the global theme', () => {
const setTheme = expect.any(Function)
const expected = {...DEFAULT_THEME, setTheme}
const {result} = renderHook(useTheme)
expect(result.current).toMatchObject(expected)
}) |
That does indeed work! However, I'm still confused: all examples should result in the same behavior. Instead, each triggers a completely different response:
|
The recent change to display @matchatype In the case that you describe:
Deep-equality matchers compare different instances of functions:
If you think of the returned data structure as a tree, there is a difference between asserting a primitive value as a leaf, and asserting a function or symbol (when the caller does not provide it as an argument). I am not sure why the work-around that you found solves the problem :) A long-term goal for Jest is to bridge gaps like this between the comparison and the report. |
The difficulty to solve those problems: is 2. medium, 1. difficult, 3. breaking |
Extremely helpful @pedrottimark Many thanks 🙏Yes, the fact that work-around actually passed totally baffled me. |
I have the same problem, for me the problem comes from the function I have in the object. toEqual in jest can compare two object, it is cool (in js we can't compare directly by '=='), but if the object contains an function (like () => {}), it will have problem to compare. |
Hi @pedrottimark, I apologise for the tardy reply; this was a weekend project and I simply got swamped with work. Yes, I am using mongoose; I did a diff on the result of
Just like @matchatype I too tried the shallow copy trick but it gave me the same error. Thank you for trying to help me troubleshoot this! I really appreciate it. |
@sabriele Thank you for the output. When I copy and paste into a local test file, there is syntax error for values of That confirms mongoose provides some methods on EDIT: That is, a method that somehow “improved” the default output from If shallow copy of the array did not help, then the next step is something like: expect(users.map(user => user.toObject())).toMatchObject(expectedUsers); See https://mongoosejs.com/docs/api.html#document_Document-toObject
If that is a solution, then I will have some follow-up questions to understand what is the problem. |
The toObject works for me |
@patran So I can understand the problem in
Paste the results after editing to delete properties that are not added by mongoose. Thank you! |
Have same problem |
I have similar problem comparing Buffers. I have tried to find any difference between these objects using |
I run into the "serializes to the same string" issue when using toMatchObject. The objects had functions defined and was the reason toMatchObject failed. I worked around the issue by mocking them: const mockFunctions = <T extends Record<string, any>>(obj: T, mock: any): T => {
const copy = { ...obj };
Reflect.ownKeys(copy)
.filter(key => typeof Reflect.get(copy, key) === "function")
.forEach(key => Reflect.set(copy, key, mock));
return copy;
}; For toMatchObject to work as expected it was important to use the same jest mock on both objects. const objectToCompare = (name: string) => {
const nameAsFunc = (): string => name;
return {
name,
nameAsFunc
};
};
describe("toMatchObject tests", () => {
it("can compare objects with functions", () => {
const mock = jest.fn();
const first = objectToCompare("name");
const second = objectToCompare("name");
// Gives "serializes to the same string"
expect(first).toMatchObject(second);
// Works
expect(mockFunctions(first, mock)).toMatchObject(mockFunctions(second, mock));
});
}); |
That worked for me too. Thanks ! |
I'm also experiencing this issue. This is my workaround: expect(JSON.stringify(result.current)).toEqual(JSON.stringify(expected)); |
@manhhailua Thank you so much! This worked for me after hours of agony.
|
@pedrottimark Are you guys planning to fix this any time soon? I am also using shallow rendering and experience bad test results. 😕 Here is my test code:
When
^ (horrible output and really should be changed) When I change the matcher to "toContainEqual" is outputs this:
(^ a failing test showing that the results are exactly the same. This is super confusing and it also should really be changed) Even using the "stringify-all-the-things" hack from @manhhailua does not work for me. It seems that the "key" field that is necessary when rendering components in a loop is hidden away in the test output. Here is my stringified test failure:
@pedrottimark Are you the maintainer of this 'react-test-renderer/shallow' project? I would very much like this to be fixed, and I have bandwidth to work on this right now if you need help. This is extremely disappointing to me as I do very much like the way 'react-test-renderer/shallow' works (much nicer than enzyme imo). It would be even nicer though if it gave more insight into why the tests are not passing! 😄 Thanks! |
In the end my test is passing with this (I was forgetting the "key" field and wasn't aware it was missing until doing the stringified comparison):
|
fyi, swapping |
Circular-structured JSONs proof:
|
In my case I had: const obj = { value: 'value', array: ['array'] };
expect(obj).toMatchObject({ ... }); And got the error, but was able to resolve that, by wrapping nested array with |
jumping onto this thread, when an object contains methods I run into this:
|
Hello. Sorry if I missed some message that was describing the issue already, but I've created a sandbox with reproduction for you: https://codesandbox.io/s/nameless-violet-vk4gn See the |
|
The difference is very minor https://jsperf.com/slice-vs-spread-2 |
Is there a way to disable "serializes to the same string" so it could resolve positively? Maybe additional configuration for Jest? Quite annoying that we have to look for a workaround every time we need to compare deep nested objects, object methods, etc. |
thx @manhhailua |
@DnEgorWeb to achieve this functionality you could serialize the objects yourself and compare the results. In my use case this behavior is a good thing because I need to make sure the objects are actually the same all the way through |
I had this problem too but I found I could wrap an expect(() => {
expect(toReact(children)).toEqual([
"Hello, ",
<A href="https://google.com">
world
</A>,
"!",
])
}).toThrow("serializes to the same string") I hope this helps someone. By the way you can actually test the throw message using regex: https://jestjs.io/docs/en/expect#tothrowerror. |
Maybe this will help somebody else. I had this error after introducing a circular dependency while writing tests. Removing the circular dependency resolved the issue. |
Got the same issue with this assert: expect(error.errors).toMatchObject(expectedErrors);
expect(Object.keys(error.errors)).toBe(Object.keys(expectedErrors)); The goal is to ensure the errors numbers are equal because I may compare array length, but the information is restricted to a simple number instead the error key diff. I finally found a workaround using expect(error.errors).toContainAllKeys(Object.keys(expectedErrors)); However, having a strict-less built-in object comparison method would be a nice addition. |
This was my solution:
|
This was my catch! TY |
Here's how I solved it. As I understand, in my case I was having a problem matching function names, because the matcher operates on the function identity, and not the name of the function. My solution was to mock the module when the function resided before running the test, the mocking ensured that all the functions have the same identity. Before (causing the test to fail with "Received: serializes to the same string" on object equality checking") import { TheInputFormControl } from '../../components/formControls';
...
it('integrates successfully', () => {
const result = getField(0);
expect(result).toMatchObject([
{
Component: TheInputFormControl,
id: 'user_id',
... After (tests passing) import { TheInputFormControl } from '../../components/formControls';
...
jest.mock('../../components/formControls'); // <- this is the secret sauce
it('integrates successfully', () => {
const result = getField(0);
expect(result).toMatchObject([
{
Component: TheInputFormControl,
id: 'user_id',
... |
Hello, import {mocked} from "ts-jest/utils" // depreciated in Jest ^28.*
import {CKTable} from "./CKTable"
jest.mock('../CKTable')
const mockedCKtable = mocked(CKTable, true)
...
const expectedOptions = {
date: new Date(),
id: 0,
// etc ...
};
const mockEntries = Object.entries(mockedCKTable.mock.calls[0][0]);
const expectedEntries = Object.entries(expectedOptions);
expect(JSON.stringify(mockEntries)).toEqual(JSON.stringify(expectedEntries)); |
This comment was marked as outdated.
This comment was marked as outdated.
I have two nearly identical components that I'm testing (via react-native-testing-library), and oddly I get this error for one, but not the other, comparing SVG components. I don't have much else useful to contribute, I'd delve deeper if I knew how to debug further. |
This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days. |
Kill the stale bot :/ |
🐛 Bug Report
Using
.toMatchObject()
returns failing test with messageReceived: serializes to the same string
To Reproduce
I am trying to check the
users
object I receive against myexpectedUsers
. The received object coming back from MongoDB contains the fields"__v"
and"_id"
which I do not want to check for (they always change for every test). As such, I am using.toMatchObject()
and cannot use something else like.toEqual()
. My test snippet is below:(
request
is made withsupertest
)Expected behavior
As documented here,
Since the
expected
objects is a subset ofreceived
objects, I expect my test to pass.npx envinfo --preset jest
resultThe text was updated successfully, but these errors were encountered: