Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
August 22, 2019 08:25 pm GMT

The difference between mocks and stubs, explained with JS

Stubs and Mocks are two foundational concepts in testing that are often misunderstood. So much so, that we have the famous Martin Fowler article on the subject, alongside numerous stackoverflow questions on the matter.
Martins article is a long read for the modern impatient reader, get somewhat sidetracked and doesn't have example in the current hype language, JS.
I'll try to be more concise in my explanations here.

I'll start with the headline definition:
Stubs and mocks are both dummy objects for testing, while stubs only implement a pre-programmed response, mocks also pre-program specific expectations.

To put it into a workflow:

Stubs

  • Setup - define the stub itself, what object in the program you are stubbing and how
  • Exercise - run the functionality you want to test
  • Verify - check the stub for values that ran through it, that they fit expectations
  • Teardown - if needed, clean up. e.g Time stubs are usually global, you need to yield control back

Mocks

  • Setup object - define the mock, what object you are mocking and how (similar to stubs)
  • Setup expectations - define what you expect will happen to this mock internally
  • Exercise - run the functionality you want to test
  • Verify mock - verify that the mock expectations are met. In some JS libraries this happens automatically without additional call, the mock expectations are verifying themselves and will throw if needed. (Used mostly when async testing).
  • Verify - verify any additional expectations for results on the mock
  • Teardown - if needed, clean up.

Mocks & Stubs in the JS community

Before we get into code, since my examples will be in JS, there is an important note to be said here.

One of the most successful testing libraries in the JS community is jest. But I will not use it for my examples, for the simple reason that jest is opinionated and does not implement mocks.
What they call a mock in the library, is actually a stub by definition. You cannot make expectations on the mock itself, rather just look at its behavior and call and make expectations on that.

I will demonstrate the concept using sinon.js that does implement the concepts of both mocks and stubs.

Stubs example

For our example, we will unit test an imaginary function for purchasing items in an eCommerce site. We will try to pay and get the payment status, and if we are successful we will send a mail.

const purchaseItemsFromCart(cartItems, user) => {  let payStatus = user.paymentMethod(cartItems)  if (payStatus === "success") {    user.sendSuccessMail()  } else {    user.redirect("payment_error_page")  }}}"when purchase payed successfully user should receive a mail" : function() {  // Setup  let paymentStub = sinon.stub().returns("success")  let mailStub = sinon.stub()  let user = {    paymentMethod: paymentStub,    sendSuccessMail: mailStub  }  // Exercise  purchaseItemsFromCart([], user)  // Verify  assert(mailStub.called)}

Mocks example

Now lets do the same, using mocks.

"when purchase payed successfully user should receive a mail" : function() {  // Setup objects  let userMock = sinon.mock({    paymentMethod: () => {},    sendSuccessMail: () => {}  })  // Setup expectations  userMock.expect(paymentMethod).returns("success")  userMock.expect(sendSuccessMail).once()  // Exercise  purchaseItemsFromCart([], user)  // Verify mocks  userMock.verify()}

Great. When should I use each?

Now this is the interesting question here.
And there is much debate - there is a reason the guys behind jest decided not to implement classic mock functionality.

Mocks can do whatever stubs can do, plus setting expectations directly on the objects they are faking.
This creates readability problems for large tests as well as tendency to start expecting and testing fake objects within the test that are not the sole purpose of the test, making it a white-box test that is too aware of internals.

That is even mentioned as a guideline in sinon documentation for when to use a mock:

Mocks should only be used for the method under test.In every unit test, there should be one unit under test.

So to not overuse this functionality and create a confusing, and maybe mispurposed test, you should limit your mocks usage in tests to one object.

Or, you know, you could just use jest that took this decision away from you by not implementing these kind of mocks in the first place.


Original Link: https://dev.to/snird/the-difference-between-mocks-and-stubs-explained-with-js-kkc

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To