Jest: Rename jest.mock to jest.stub

Created on 9 Jan 2019  路  9Comments  路  Source: facebook/jest

馃殌 Feature Proposal

It would be better to rename jest.mock to jest.stub, because actually what it is doing is stubbing the objects. It doesn't have pre-programmed expectations like mocks have.

Motivation

I love jest and using it for a quite while now. But jest.mock doesn't do what mocks do and that naming bothers me a little bit. I did a lot of research about testing and noticed that we are often using the term mock wrong in js community.

I started my research based on this article but almost all articles I've read confirm this statement: https://martinfowler.com/articles/mocksArentStubs.html

I know it's a major change and I don't know if you already considered this and wanted to go with the term mock because it's more often used, however I think renaming it would bring value by avoiding confusions like I had.

Example

Here some of the documents that I've came across.

Pitch

This is a change to an existing Jest feature.

New API proposal

Most helpful comment

I'm using jest for quite some time now and I also didn't care about it. I just read the jest's official documentation and started writing my tests.

But I recently gave a presentation about testing and in that tried to explain the terminology, and then of course, I suggested to use jest being my favourite test runner at the moment. But then jest.mock API created confusion between some of the listeners because I defined mocks based on what I've read in most articles.

@jeysal I totally understand your argument and it is a minor detail, but it's a detail and seems like it doesn't fit with the literature. And definitely, I'm not an expert on this, I just spent quite some time with testing and read some, and as you said my understanding can be wrong. I'm aware that I'm suggesting this change to the developers who created the most popular testing framework existing at the moment. It's up to them to follow the old terminology or set the new ones.

The thing I care about is Javascript always had issues with standardisation. By now we are in much better shape but we still need to make progress.

I was inspired by Denis Radin's question "Would you get on a plane if it uses Javascript?" in this talk Denis Radin: Applying NASA coding standards to JavaScript | JSConf EU 2017
. And since then I'm trying to be more careful on following community standards. All I want is to see more unified JS community and I just wanted to raise my concern on this :)

All 9 comments

We have jest.mock('thing', factory), there stub would be wrong. Not sure if it's worth having 2 APIs?

Hmm I'm not sure if there stub would be that wrong because we would still use the factory to return jest.fn() or an intercepted module object. And I am not sure if we would define the assertions in the factory?

I think you may be interpreting "pre-programmed expectations" too narrowly. I don't think it requires the expectations to be defined "before the call happens at runtime" or "above the call in the source code" or something like that. I believe it means that we "pre-program" the expectations when writing the test, so it can still be a mock if the expectation is below the usage of the mock:

const mock = jest.fn();
mock(42); // happens somewhere in the SUT
expect(mock).toHaveBeenCalledWith(42);

I'm happy to be corrected though if you can link me to some literature that is more explicit about this.

The whole "mock"/"stub"/"spy" stuff was very off-putting at the very beginning when I started testing because it's so hard to find a right answer to which is which (or was at the time; MS article tries really well to fix it, which is great). I still see no added value to differentiate that.

In Jest I see mock as a _Fake_ (according to Microsoft nomenclature) because it's very expressive and generic and I'm happy with that. I'd rather consider changing mock to fake and left users to choose which is mock which is stub (who cares tho?), but anyway that would be _pretty_ breaking and I'm against the change, at least in a foreseeable future.

EDIT:
Once we settle down on which is more appropriate, we could, however, introduce aliases and promote new APIs, and eventually drop old syntax.

FWIW sinon merged spies and stubs into fakes in v5: https://sinonjs.org/releases/latest/fakes/

@jeysal In general practice, mocks have sort of a verification method and you call it after defining the expectations (see mock.verify() line here: https://sinonjs.org/releases/v7.2.2/mocks/) Also you may wanna take a look the links in example section for further references. In the example you gave, you simply do your assertion inside the tests and you are using a stub which is totally fine, but I wouldn't consider that example as a mock example.

@thymikee after reading your comment, now I also think using fake and leaving interpretation to user makes much more sense and it's a better for general use I suppose. But then we need to think about what to do with spyOn. Also, i would insist fake still wouldn't be a mock tho :)

And I also think introducing alternative API and deprecating old ones with upcoming releases is a good way to go. Thanks for elaborating the idea.

A bit related to #6180 if we wanna mess with the overall API anyways, /cc @mattphillips @rickhanlonii

@jeysal In general practice, mocks have sort of a verification method and you call it after defining the expectations (see mock.verify() line here: sinonjs.org/releases/v7.2.2/mocks) Also you may wanna take a look the links in example section for further references. In the example you gave, you simply do your assertion inside the tests and you are using a stub which is totally fine, but I wouldn't consider that example as a mock example.

Sure, I am aware that a verify method is a common pattern for mocks, but I disagree that it is what distinguishes them from stubs.
The difference between the approach of Sinon (and most others)

fn should be called once with argument 42.
do stuff.
verify that expected call on fn occurred.

and the approach of Jest

do stuff.
verify that fn has been called once with argument 42.

is IMO a very minor detail.

What distinguishes them from stubs is that they perform assertions on the calls that have occurred on them, while stubs exist to provide canned return values.
jest.fn()s support both types of usage.

I'm using jest for quite some time now and I also didn't care about it. I just read the jest's official documentation and started writing my tests.

But I recently gave a presentation about testing and in that tried to explain the terminology, and then of course, I suggested to use jest being my favourite test runner at the moment. But then jest.mock API created confusion between some of the listeners because I defined mocks based on what I've read in most articles.

@jeysal I totally understand your argument and it is a minor detail, but it's a detail and seems like it doesn't fit with the literature. And definitely, I'm not an expert on this, I just spent quite some time with testing and read some, and as you said my understanding can be wrong. I'm aware that I'm suggesting this change to the developers who created the most popular testing framework existing at the moment. It's up to them to follow the old terminology or set the new ones.

The thing I care about is Javascript always had issues with standardisation. By now we are in much better shape but we still need to make progress.

I was inspired by Denis Radin's question "Would you get on a plane if it uses Javascript?" in this talk Denis Radin: Applying NASA coding standards to JavaScript | JSConf EU 2017
. And since then I'm trying to be more careful on following community standards. All I want is to see more unified JS community and I just wanted to raise my concern on this :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

timoxley picture timoxley  路  76Comments

paularmstrong picture paularmstrong  路  66Comments

SimenB picture SimenB  路  69Comments

vitalibozhko picture vitalibozhko  路  138Comments

iffy picture iffy  路  137Comments