Thanks! We'll be in touch in the next 12 hours
Oops! Something went wrong while submitting the form.

Beginner’s Guide for Writing Unit Test Cases with Jest Framework

Siddharth Jain

Unit Testing/ Backend Development

Prerequisite

Basic JavaScript, TypeScript

Objective

To make the reader understand the use/effect of test cases in software development.

What’s in it for you?

In the world of coding, we're often in a rush to complete work before a deadline hits. And let's be honest, writing test cases isn't usually at the top of our priority list. We get it—they seem tedious, so we’d rather skip this extra step. But here's the thing: those seemingly boring lines of code have superhero potential. Don't believe me? You will.

In this blog, we're going to break down the mystery around test cases. No jargon, just simple talk. We'll chat about what they are, explore a handy tool called Jest, and uncover why these little lines are actually the unsung heroes of coding. So, let's ditch the complications and discover why giving some attention to test cases can level up our coding game. Ready? Let's dive in!

What are test cases?

A test case is a detailed document specifying conditions under which a developer assesses whether a software application aligns with customer requirements. It includes preconditions, the case name, input conditions, and expected results. Derived from test scenarios, test cases cover both positive and negative inputs, providing a roadmap for test execution. This one-time effort aids future regression testing.

Test cases offer insights into testing strategy, process, preconditions, and expected outputs. Executed during testing, they ensure the software performs its intended tasks. Linking defects to test case IDs facilitates efficient defect reporting. The comprehensive documentation acts as a safeguard, catching any oversights during test case execution and reinforcing the development team's efforts.

Different types of test cases exist, including integration, functional, non-functional, and unit.
For this blog, we will talk about unit test cases.

What are unit test cases?

Unit testing is the process of testing the smallest functional unit of code. A functional unit could be a class member or simply a function that does something to your input and provides an output. Test cases around those functional units are called unit test cases.

Purpose of unit test cases

  • To validate that each unit of the software works as intended and meets the requirements:
    For example, if your requirement is that the function returns an object with specific properties, a unit test will detect whether the code is written accordingly.
  • To check the robustness of code:
    Unit tests are automated and run each time the code is changed to ensure that new code does not break existing functionality.
  • To check the errors and bugs beforehand:
    If a case fails or doesn’t fulfill the requirement, it helps the developer isolate the area and recheck it for bugs before testing on demo/UAT/staging.

Different frameworks for writing unit test cases

There are various frameworks for unit test cases, including:

  • Mocha
  • Storybook
  • Cypress
  • Jasmine
  • Puppeteer
  • Jest
Source: https://raygun.com/blog/javascript-unit-testing-frameworks/

Why Jest?

Jest is used and recommended by Facebook and officially supported by the React dev team.

It has a great community and active support, so if you run into a problem and can’t find a solution in the comprehensive documentation, there are thousands of developers out there who could help you figure it out within hours.

1. Performance: Ideal for larger projects with continuous deployment needs, Jest delivers enhanced performance.

2. Compatibility: While Jest is widely used for testing React applications, it seamlessly integrates with other frameworks like Angular, Node, Vue, and Babel-based projects.

3. Auto Mocking: Jest automatically mocks imported libraries in test files, reducing boilerplate and facilitating smoother testing workflows.

4. Extended API: Jest comes with a comprehensive API, eliminating the necessity for additional libraries in most cases.

5. Timer Mocks: Featuring a Time mocking system, Jest accelerates timeout processes, saving valuable testing time.

6. Active Development & Community: Jest undergoes continuous improvement, boasting the most active community support for rapid issue resolution and updates.

Components of a test case in Jest

Describe

  • As the name indicates, they are responsible for describing the module we are going to test.
  • It should only describe the module, not the tests, as this describe module is generally not tested by Jest.

It

  • Here, the actual code is tested and verified with actual or fake (spy, mocks) outputs.
    We can nest various it modules under the describe module.
  • It’s good to describe what the test does or doesn’t do in the description of the it module.

Matchers

  • Matchers match the output with a real/fake output.
  • A test case without a matcher will always be a true/trivial test case.

CODE: https://gist.github.com/velotiotech/dd4149c046fe565b0235fb8f7156f821.js

Mocks and spies in Jest

Mocks: They are objects or functions that simulate the behavior of real components. They are used to create controlled environments for testing by replacing actual components with simulated ones. Mocks are employed to isolate the code being tested, ensuring that the test focuses solely on the unit or component under examination without interference from external dependencies.

It is mainly used for mocking a library or function that is most frequently used in the whole file or unit test case.

Let Code.ts be the file you want to test.

CODE: https://gist.github.com/velotiotech/cb8b6d9fa6b14c2ae3278b9f7e945385.js

As this is a unit test, we won't be testing the uuidV4 function, so we will mock the whole uuid module using jest.mock.

CODE: https://gist.github.com/velotiotech/53a3bf0854c00aed14b1956e6215b4ae.js

And that's it. You have mocked the entire uuid module, so when it is coded during a test, it will return uuidV4 function, and that function, when executed, will give a random id value.

Spies: They are functions or objects that "spy" on other functions by tracking calls made to them. They allow you to observe and verify the behavior of functions during testing. Spies are useful for checking if certain functions are called, how many times they are called, and with what arguments. They help ensure that functions are interacting as expected.

This is by far the most used method, as this method works on object values and thus can be used to spy class methods efficiently.

CODE: https://gist.github.com/velotiotech/b1b4ed390ae06cd8de9de163505a8ac3.js

CODE: https://gist.github.com/velotiotech/7fc0ac06ce64666489caaf2359329117.js

Mocking database call

One of the best uses of Jest is to mock a database call, i.e., mocking create, put, post, and delete calls for a database table.

We can complete the same action with the help of only Jest spies.

Let us suppose we have a database called DB, and it has lots of tables in it. Let’s say it has Table Student in it, and we want to mock create a Student database call.

CODE: https://gist.github.com/velotiotech/db4f5901de9c75d0fcd89b55a5929e3d.js

Now, as we are using the Jest spy method, we know that it will only be applicable to objects, so we will first make the Db. Students table into an object with create as method inside it, which will be jest.fn() (a function which can be used for mocking functions).

Students an object with create as method inside object which will be jest.fn() (a function which can be used for mocking functions in one line without actually calling that function).

CODE: https://gist.github.com/velotiotech/cbf9b328aed8caeed29e44b06061ff09.js

Testing private methods

Sometime, in development, we write private code for classes that can only be used within the class itself. But when writing test cases, we call the function by creating a class instance, and the private functions won’t be accessible to us, so we will not be able to test private functions.

But in core JavaScript, there is no concept of private and public functions; it is introduced to us as TypeScript. So, we can actually test the private function as a normal public function by using the //@ts-ignore comment just above calling the private function.

CODE: https://gist.github.com/velotiotech/e4dbe5a4b89f375adfb2ba81bbc780db.js

CODE: https://gist.github.com/velotiotech/3443d998e8caa701c48ed9d3d1928b84.js

P.S. One thing to note is that this will only work with TypeScript/JavaScript files.

The importance of test cases in software development

Makes code agile:

In software development, one may have to change the structure or design of your code to add new features. Changing the already-tested code can be risky and costly. When you do the unit test, you just need to test the newly added code instead of the entire program.

Improves code quality:

A lot of bugs in software development occur due to unforeseen edge cases. If you forget to predict a single input, you may encounter a major bug in your application. When you write unit tests, think carefully about the edge cases of every function in your application.

Provides Documentation:

The unit test gives a basic idea of what the code does, and all the different use cases are covered through the program. It makes documentation easier, increasing the readability and understandability of the code. Anytime other developers can go through the unit test interface, understand the program better, and work on it fast and easily.

Easy Debugging:

Unit testing has made debugging a lot easier and quicker. If the test fails at any stage, you only need to debug the latest changes made in the code instead of the entire program. We have also mentioned how unit testing makes debugging easier at the next stage of integration testing as well.

Conclusion

So, if you made it to the end, you must have some understanding of the importance of test cases in your code.

We’ve covered the best framework to choose from and how to write your first test case in Jest. And now, you are more confident in proving bug-free, robust, clean, documented, and tested code in your next MR/PR.

Get the latest engineering blogs delivered straight to your inbox.
No spam. Only expert insights.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings

You may also like

No items found.

Beginner’s Guide for Writing Unit Test Cases with Jest Framework

Prerequisite

Basic JavaScript, TypeScript

Objective

To make the reader understand the use/effect of test cases in software development.

What’s in it for you?

In the world of coding, we're often in a rush to complete work before a deadline hits. And let's be honest, writing test cases isn't usually at the top of our priority list. We get it—they seem tedious, so we’d rather skip this extra step. But here's the thing: those seemingly boring lines of code have superhero potential. Don't believe me? You will.

In this blog, we're going to break down the mystery around test cases. No jargon, just simple talk. We'll chat about what they are, explore a handy tool called Jest, and uncover why these little lines are actually the unsung heroes of coding. So, let's ditch the complications and discover why giving some attention to test cases can level up our coding game. Ready? Let's dive in!

What are test cases?

A test case is a detailed document specifying conditions under which a developer assesses whether a software application aligns with customer requirements. It includes preconditions, the case name, input conditions, and expected results. Derived from test scenarios, test cases cover both positive and negative inputs, providing a roadmap for test execution. This one-time effort aids future regression testing.

Test cases offer insights into testing strategy, process, preconditions, and expected outputs. Executed during testing, they ensure the software performs its intended tasks. Linking defects to test case IDs facilitates efficient defect reporting. The comprehensive documentation acts as a safeguard, catching any oversights during test case execution and reinforcing the development team's efforts.

Different types of test cases exist, including integration, functional, non-functional, and unit.
For this blog, we will talk about unit test cases.

What are unit test cases?

Unit testing is the process of testing the smallest functional unit of code. A functional unit could be a class member or simply a function that does something to your input and provides an output. Test cases around those functional units are called unit test cases.

Purpose of unit test cases

  • To validate that each unit of the software works as intended and meets the requirements:
    For example, if your requirement is that the function returns an object with specific properties, a unit test will detect whether the code is written accordingly.
  • To check the robustness of code:
    Unit tests are automated and run each time the code is changed to ensure that new code does not break existing functionality.
  • To check the errors and bugs beforehand:
    If a case fails or doesn’t fulfill the requirement, it helps the developer isolate the area and recheck it for bugs before testing on demo/UAT/staging.

Different frameworks for writing unit test cases

There are various frameworks for unit test cases, including:

  • Mocha
  • Storybook
  • Cypress
  • Jasmine
  • Puppeteer
  • Jest
Source: https://raygun.com/blog/javascript-unit-testing-frameworks/

Why Jest?

Jest is used and recommended by Facebook and officially supported by the React dev team.

It has a great community and active support, so if you run into a problem and can’t find a solution in the comprehensive documentation, there are thousands of developers out there who could help you figure it out within hours.

1. Performance: Ideal for larger projects with continuous deployment needs, Jest delivers enhanced performance.

2. Compatibility: While Jest is widely used for testing React applications, it seamlessly integrates with other frameworks like Angular, Node, Vue, and Babel-based projects.

3. Auto Mocking: Jest automatically mocks imported libraries in test files, reducing boilerplate and facilitating smoother testing workflows.

4. Extended API: Jest comes with a comprehensive API, eliminating the necessity for additional libraries in most cases.

5. Timer Mocks: Featuring a Time mocking system, Jest accelerates timeout processes, saving valuable testing time.

6. Active Development & Community: Jest undergoes continuous improvement, boasting the most active community support for rapid issue resolution and updates.

Components of a test case in Jest

Describe

  • As the name indicates, they are responsible for describing the module we are going to test.
  • It should only describe the module, not the tests, as this describe module is generally not tested by Jest.

It

  • Here, the actual code is tested and verified with actual or fake (spy, mocks) outputs.
    We can nest various it modules under the describe module.
  • It’s good to describe what the test does or doesn’t do in the description of the it module.

Matchers

  • Matchers match the output with a real/fake output.
  • A test case without a matcher will always be a true/trivial test case.

CODE: https://gist.github.com/velotiotech/dd4149c046fe565b0235fb8f7156f821.js

Mocks and spies in Jest

Mocks: They are objects or functions that simulate the behavior of real components. They are used to create controlled environments for testing by replacing actual components with simulated ones. Mocks are employed to isolate the code being tested, ensuring that the test focuses solely on the unit or component under examination without interference from external dependencies.

It is mainly used for mocking a library or function that is most frequently used in the whole file or unit test case.

Let Code.ts be the file you want to test.

CODE: https://gist.github.com/velotiotech/cb8b6d9fa6b14c2ae3278b9f7e945385.js

As this is a unit test, we won't be testing the uuidV4 function, so we will mock the whole uuid module using jest.mock.

CODE: https://gist.github.com/velotiotech/53a3bf0854c00aed14b1956e6215b4ae.js

And that's it. You have mocked the entire uuid module, so when it is coded during a test, it will return uuidV4 function, and that function, when executed, will give a random id value.

Spies: They are functions or objects that "spy" on other functions by tracking calls made to them. They allow you to observe and verify the behavior of functions during testing. Spies are useful for checking if certain functions are called, how many times they are called, and with what arguments. They help ensure that functions are interacting as expected.

This is by far the most used method, as this method works on object values and thus can be used to spy class methods efficiently.

CODE: https://gist.github.com/velotiotech/b1b4ed390ae06cd8de9de163505a8ac3.js

CODE: https://gist.github.com/velotiotech/7fc0ac06ce64666489caaf2359329117.js

Mocking database call

One of the best uses of Jest is to mock a database call, i.e., mocking create, put, post, and delete calls for a database table.

We can complete the same action with the help of only Jest spies.

Let us suppose we have a database called DB, and it has lots of tables in it. Let’s say it has Table Student in it, and we want to mock create a Student database call.

CODE: https://gist.github.com/velotiotech/db4f5901de9c75d0fcd89b55a5929e3d.js

Now, as we are using the Jest spy method, we know that it will only be applicable to objects, so we will first make the Db. Students table into an object with create as method inside it, which will be jest.fn() (a function which can be used for mocking functions).

Students an object with create as method inside object which will be jest.fn() (a function which can be used for mocking functions in one line without actually calling that function).

CODE: https://gist.github.com/velotiotech/cbf9b328aed8caeed29e44b06061ff09.js

Testing private methods

Sometime, in development, we write private code for classes that can only be used within the class itself. But when writing test cases, we call the function by creating a class instance, and the private functions won’t be accessible to us, so we will not be able to test private functions.

But in core JavaScript, there is no concept of private and public functions; it is introduced to us as TypeScript. So, we can actually test the private function as a normal public function by using the //@ts-ignore comment just above calling the private function.

CODE: https://gist.github.com/velotiotech/e4dbe5a4b89f375adfb2ba81bbc780db.js

CODE: https://gist.github.com/velotiotech/3443d998e8caa701c48ed9d3d1928b84.js

P.S. One thing to note is that this will only work with TypeScript/JavaScript files.

The importance of test cases in software development

Makes code agile:

In software development, one may have to change the structure or design of your code to add new features. Changing the already-tested code can be risky and costly. When you do the unit test, you just need to test the newly added code instead of the entire program.

Improves code quality:

A lot of bugs in software development occur due to unforeseen edge cases. If you forget to predict a single input, you may encounter a major bug in your application. When you write unit tests, think carefully about the edge cases of every function in your application.

Provides Documentation:

The unit test gives a basic idea of what the code does, and all the different use cases are covered through the program. It makes documentation easier, increasing the readability and understandability of the code. Anytime other developers can go through the unit test interface, understand the program better, and work on it fast and easily.

Easy Debugging:

Unit testing has made debugging a lot easier and quicker. If the test fails at any stage, you only need to debug the latest changes made in the code instead of the entire program. We have also mentioned how unit testing makes debugging easier at the next stage of integration testing as well.

Conclusion

So, if you made it to the end, you must have some understanding of the importance of test cases in your code.

We’ve covered the best framework to choose from and how to write your first test case in Jest. And now, you are more confident in proving bug-free, robust, clean, documented, and tested code in your next MR/PR.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings