Skip to content
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

Partial matching for mock assertions #2137

Closed
jwbay opened this issue Nov 20, 2016 · 11 comments
Closed

Partial matching for mock assertions #2137

jwbay opened this issue Nov 20, 2016 · 11 comments

Comments

@jwbay
Copy link
Contributor

jwbay commented Nov 20, 2016

Do you want to request a feature or report a bug?
Feature

What is the current behavior?
Asserting on parts of calls to mocks requires inspecting arguments or using a jasmine API

What is the expected behavior?
Asserting on parts of calls to mocks has a first-class API

Related - #1843

Currently, asserting that a mock was called with a complex object is less than ideal because you have to either supply the entire matching object, use jasmine.objectContaining, or inspect the calls yourself with .mock.calls[x][y]. I'd like to propose an API like the following.

const mock = jest.fn();
mock({
	one: 'very long string',
	two: 2,
	three: '',
	four: {
		x: '42'
	}
});

expect(mock).toHaveBeenCalledWithMatch({
	one: 'very long string',
	two: 2
});

expect(mock).toHaveBeenCalledWithMatch({
	two: jest.any(Number) //like jasmine.any(Class)
});

Ideally we could go even further and add some meta-matchers to the jest object (inspired by sinon's matchers) to unlock some powerful assertions.

expect(mock).toHaveBeenCalledWithMatch({
	one: jest.match(value => value.startsWith('very')),
	two: jest.match.number(), //instead of jest.any(Number)
	three: jest.match.falsy(),
	four: jest.match.has('x')
});
@thymikee
Copy link
Collaborator

Have you tried using asymmetric matchers? They are exposed through expect. http://facebook.github.io/jest/docs/api.html#asymmetric-jest-matchers

@thymikee
Copy link
Collaborator

Worth noting they're available since Jest 18.
And will be provided with pretty-printing soon

@thymikee
Copy link
Collaborator

Disregard my previous comments.

Nevertheless I'm not convinced we need another type of matchers, because it's all possible through asymmetric matchers (now ported to Jest) without much more typing.

e.g. you can use

expect(mock).toHaveBeenCalledWith(expect.objectContaining({
  two: expect.any(Number)
}));

@cpojer
Copy link
Member

cpojer commented Jan 11, 2017

yep, agree with @thymikee here.

@cpojer cpojer closed this as completed Jan 11, 2017
@andyearnshaw
Copy link
Contributor

@thymikee @cpojer that's a shame. Doing something like this is not as simple with jest matchers alone:

expect(mock).toHaveBeenCalledWith(expect.objectContaining({
    value: sinon.match(v => v >= 100 && v < 200)
});

There are times when .any() just doesn't cut it.

@benmvp
Copy link

benmvp commented Oct 12, 2017

Thanks @thymikee! This solved my problem! 😄

@alfechner
Copy link

@andyearnshaw your example is the first thing which came to my mind when I read the solution provided by @thymikee.

I currently have an object which I expect to be passed to my mocked method. It's not the same instance, though. It just represents the same value and has the same internal state. A method like sinon.match would be super handy for this use case.

@SimenB
Copy link
Member

SimenB commented Mar 14, 2019

You can add custom asymmetric matchers today (toBeWithinRange in the docs: https://jestjs.io/docs/en/expect#expectextendmatchers). expect.match or expect.predicate sounds pretty cool.

@briantical
Copy link

@thymikee you just saved me after countless hours of coding. Thanks. Your solution worked for me.

@tabrez96
Copy link

@thymikee You made my day

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

9 participants