Mocking chained functions with Jest
Took me a long time to learn how to mock/stub in my tests.
I like to make fun of things, but mocking functions is not my favourite pastime.
Too soon ? Oh well...
Don't worry, I promise, no more puns in this article. Aaah-wait I lied.
Seriously tho, were here to talk about testing and the difficulties when testing more than an example function from a tutorial.
I've always found that writing tests is easy for standalone functions.
However, it becomes disproportionately hard as soon as you try to test a function that uses a third-party library and requires mocking/stubbing, especially with chained functions/methods.
Now, let's discuss how to mock the Google Cloud SDK's BigQuery Node.JS API using their sample code:
Note: Although it may seem, upon reading this, that I figured things out quickly, on the contrary, the process involved a few hours of head-banging, reading articles, documentation, source codes, StackOverflow, and nagging ChatGPT and my colleague JP.
The task
My task at hand was quite simple: insert a single row into a BigQuery table. I grabbed the example and quickly set my function up then went on to write some tests, covering the scenarios that can arise when the my function is called.
The stuff that didn't work
Initially, I thought just mocking the class with Jest will work just fine, but things kept erroring.
Later, I switched to mock implementation, but it still didn't fully work. It passed for toHaveBeenCalledWith
for the first chained function of .table()
but not for the subsequent ones.
This got me thinking and made me look at the type signatures and implementation of the bigquery
package itself in my node modules.
The realisation
Then, the realisation struck.
The return type of bigquery.dataset
class included a line indicating that it returns a function called table
.
Upon further investigation, I found a similar pattern. Each function returns a class containing the next function I was trying to use, so my mock implementation needed to account for this.
The solution
The function
The working test
Additional resources
- https://www.appsloveworld.com/jestjs/3/mock-new-function-with-jest
- https://getsimple.works/how-to-mock-chained-functions
- https://stackoverflow.com/questions/62492844/mocking-es6-bigquery-class
- https://jestjs.io/docs/mock-function-api
- https://stackoverflow.com/questions/45771844/mock-mockimplementation-not-working