The jest mock functions docs (https://jestjs.io/docs/en/mock-functions) show them using the .mock.calls.length property for assertions about spies. What is the difference between
const myFunc = jest.fn()
myFunc();
expect(myFunc.mock.calls.length).toBe(1)
and
const myFunc = jest.fn()
myFunc();
expect(myFunc).toHaveBeenCalledTimes(1)
?
Is it just sugar? When should the user use the mock object?
Yes, those matchers are sugar, but, of course, they don't cover all the possible scenarios one may want to assert. If the user don't have on them what they need, they'll have to use the .mock property.
In jest docs (https://jestjs.io/docs/mock-functions), this is clearly stated under the Custom Matchers title:
Finally, in order to make it less demanding to assert how mock functions have been called, we've added some custom matcher functions for you:
*** matcher function examples ***
These matchers are sugar for common forms of inspecting the .mock property. You can always do this manually yourself if that's more to your taste or if you need to do something more specific.
Related
I'm used to do mocking (actually, faking, but, whatever) with Sinon.js by using withArgs extensively to conditionally return the fake value. And now I'm trying to migrate to Jest and I'm can't find anything similar in the mock API.
What I want:
const t = sinon.stub();
t.withArgs('foo').returns('bar');
console.log(t('foo')); // 'bar'
console.log(t('qux')); // undefined
It seems that the only way to do that in Jest is by using mockImplementation, which means that I must write the arg matcher by hand.
Is there a better way of doing this in Jest?
So far, there isn't any Jest builtin method.
There is an issue opened here and a feature proposal here.
Based on this question, there is a third party library that does something similar: https://github.com/timkindberg/jest-when
I'm reading the mocking capability of minitest.
require "minitest/autorun"
mock = MiniTest::Mock.new
mock.expect(:use_any_string, true, [String])
mock.use_any_string("foo")
## mock.use_any_string(1)
## MockExpectationError: mocked method :use_any_string called with unexpected arguments [1]
## I do not understand the purpose for this
mock.verify
So I do not understand the purpose of using mock.verify since the trying to pass any another type(to use_any_string) other than String result in mock expectation error.
So why should one use assert mock.verify then?
You are right, you cannot set anything else to the configured mock, but if your mock is not called at all, then you can find out with mock.verify. So if your method under test should call the mocked method, you should verify that it was called at all.
You are correct, mock.expect(:use_any_string, true, [String]) will cause the test to fail if the expected call is not made on the mock.
However using mock.verify depends on how you compose your test. In your example you are explicitly calling the method you are testing with mock.use_any_string("foo") so there is no need to also call mock.verify.
You could get into a scenario where you are not making this call explicitly, or are expecting the mock to have had calls made at a certain time. These scenarios would take advantage of mock.verify calls.
(Another note, minitest has recently introduced assert_mock which can be used instead of mock.verify)
I just started investigation of Sinon.JS and after some research I stuck with the following two methods and do not know how exactly they are working:
sinon.fake.yields(callback[, value1, ..., valueN]);
and
sinon.fake.yieldsAsync(callback[, value1, ..., valueN]);
It would be great if somebody explain (or even show some example) how they work and when should I use them. One more important question what is the difference between fake, stub and mock in common?
Thanks in advance!
The Sinon docs explain that yields() returns a fake that "expects the last argument to be a callback and will invoke it with the given arguments".
yieldsAsync() does the same thing but invokes the callback asynchronously.
Looking at the Sinon source code makes it clear exactly what this means:
Calling sinon.fake.yields(...) records the arguments passed and returns a function.
When the returned function is invoked it ignores all of its own arguments except the last one which it assumes is a callback. It then invokes that callback with the arguments it recorded from when it was created with yields():
import * as sinon from 'sinon';
const fake = sinon.fake.yields('arguments', 'passed', 'to', 'yields');
const callback = (...args) => {
console.log(args);
}
// logs the following to the console:
// [ 'arguments', 'passed', 'to', 'yields' ]
fake('every argument', 'except the last', 'is ignored', callback);
yieldsAsync() does exactly the same thing except that it invokes the callback asynchronously.
In Sinon, a spy "is a function that records arguments, return value, the value of this and exception thrown (if any) for all its calls". It just spies on the calls made to it. It can either wrap nothing or it can wrap and transparently pass through to an existing function.
A stub is a spy "with pre-programmed behavior". A stub lets you spy on the calls made to it and also lets you define how the function should behave (return value, exception thrown, etc.). If an existing function is wrapped in a stub the behavior defined by the stub is used instead of the function.
"fake was introduced with Sinon with v5. It simplifies and merges concepts from spies and stubs." It spies on the calls made to it like both spies and stubs, it can be created with or without behavior and it can also wrap an existing function.
A mock is a fake method "with pre-programmed behavior...as well as pre-programmed expectations". A mock lets you define how the function should behave and also how it is expected to be used. Calling verify() on a mock will fail if the mock was not used as expected.
In Jest there are functions like tobeCalled or toBeCalledWith to check if a particular function is called.
Is there any way to check that a function is not called?
Just use not.
expect(mockFn).not.toHaveBeenCalled()
See the jest documentation
not did not work for me, throwing a Invalid Chai property: toHaveBeenCalled
But using toHaveBeenCalledTimes with zero does the trick:
expect(mock).toHaveBeenCalledTimes(0)
Recent versions of Jest (22.x and onwards) collect quite decent statistics of mock functions calls, just check out their docs.
The calls property shows you the number of calls, the arguments passed to the mock, the result returned out of it and whatnot. You can access it directly, as a property of mock (e.g. in a way how #Christian Bonzelet suggested in his answer):
// The function was called exactly once
expect(someMockFunction.mock.calls.length).toBe(1);
// The first arg of the first call to the function was 'first arg'
expect(someMockFunction.mock.calls[0][0]).toBe('first arg');
// The second arg of the first call to the function was 'second arg'
expect(someMockFunction.mock.calls[0][1]).toBe('second arg');
I personally prefer this way as it gives you more flexibility and keeps code cleaner in case if you test for different inputs that produce a different number of calls.
However, you can also use shorthand aliases for Jest's expect since recently (spy matchers aliases PR). I guess .toHaveBeenCalledTimes would suit fine here:
test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenCalledTimes(2); // or check for 0 if needed
});
In rare cases, you might even want to consider writing your own fixture that'd do the counting. It could be useful if you're heavy on conditioning or working with state, for example.
Hope this helps!
Please follow the documentation from jest:
https://jestjs.io/docs/en/mock-functions#mock-property
All mock functions have this special .mock property, which is where data about how the function has been called and what the function returned is kept. The .mock property also tracks the value of this for each call, so it is possible to inspect this as well: [...]
These mock members are very useful in tests to assert how these functions get called, instantiated, or what they returned:
// The function was called exactly once
expect(someMockFunction.mock.calls.length).toBe(1);
Or...
// The function was not called
expect(someMockFunction.mock.calls.length).toBe(0);
In my attempt to mock an object in Groovy using the mock.interceptor package:
def mock = new MockFor(TheClass);
mock.demand.theMethod{ "return" }
mock.use {
def underTest = new TheClass()
println underTest.theMethod()
}
The problem I have is when creating TheClass() in the use{ block, it uses the actual constructor which, in this circumstance, I'd rather it not use. How can I create an instance of this class so I can test the method I do care about, theMethod, without needing to use the constructor?
Using EasyMock/CE, mocks can be made without using the constructor, but am curious how to achieve that in Groovy.
I recently saw a presentation by the author of GMock and it has some hooks to allow "constructor" mocking which I think is what you are after.
e.g.
def mockFile = mock(File, constructor('/a/path/file.txt'))
This library differs from that "built in" to groovy, however it looked very well written, with some thought put into the kinds of things you want to mock and more importantly the error messages you would get when tests should fail.
I think this is what you are after. I would say use constructor mocking with care - it could be a smell that you should inject a Factory object, but for some things it looked to work well.
You can use the interceptConstruction flag when calling MockFor, see
MockFor.