[Unit Testing] Fundamentals of Testing in Javascript

In this lesson, we’ll get the most fundamental understanding of what an automated test is in JavaScript. A test is code that throws an error when the actual result of something does not match the expected output. 

Tests can get more complicated when you’re dealing with code that depends on some state to be set up first (like a component needs to be rendered to the document before you can fire browser events, or there needs to be users in the database). However, it is relatively easy to test pure functions (functions which will always return the same output for a given input and not change the state of the world around them).

 

Base file to test against:

math.js

const sum = (a, b) => a - b;
const subtract = (a, b) => a - b;

const sumAsync = (...args) => Promise.resolve(sum(...args));
const subtractAsync = (...args) => Promise.resolve(subtract(...args));

module.exports = { sum, subtract, sumAsync, subtractAsync };

 index.js

复制代码
const { sum, subtract } = require("./math");

let result, expected;

result = sum(3, 7);
expected = 10;
if (actual !== expected) {
   throw new Error(`${result} is not equal to ${expected}`);
}

result = subtract(7, 3);
expected = 4;
if (actual !== expected) {
   throw new Error(`${result} is not equal to ${expected}`);
}
复制代码

 

Let’s add a simple layer of abstraction in our simple test to make writing tests easier. The assertion library will help our test assertions read more like a phrase you might say which will help people understand our intentions better. It will also help us avoid unnecessary duplication.

复制代码
const { sum, subtract } = require("./math");

let result, expected;

result = sum(3, 7);
expected = 10;
expect(result).toBe(expected);

result = subtract(7, 3);
expected = 4;
expect(result).toBe(expected);

function expect(actual) {
  return {
    toBe(expected) {
      if (actual !== expected) {
        throw new Error(`${actual} is not equal to ${expected}`);
      }
    }
  };
}
复制代码

This is also a common way to write a assetion library, expect() function take a actual value and return an object contains 'toBe', 'toEqual'... functions.

 

One of the limitations of the way that this test is written is that as soon as one of these assertions experiences an error, the other tests are not run. It can really help developers identify what the problem is if they can see the results of all of the tests.

Let’s create our own test function to allow us to encapsulate our automated tests, isolate them from other tests in the file, and ensure we run all the tests in the file with more helpful error messages.

复制代码
const { sum, subtract } = require("./math");

let result, expected;

test("sum adds numbers", () => {
  result = sum(3, 7);
  expected = 10;
  expect(result).toBe(expected);
});

test("subtract substracts numbers", () => {
  result = subtract(7, 3);
  expected = 4;
  expect(result).toBe(expected);
});

function test(title, cb) {
  try {
    cb();
    console.log(`%c ✔︎ ${title}`, "color: green");
  } catch (err) {
    console.error(`✘ ${title}`);
    console.error(err);
  }
}
复制代码

 

Our testing framework works great for our synchronous test. What if we had some asynchronous functions that we wanted to test? We could make our callback functions async, and then use the await keyword to wait for that to resolve, then we can make our assertion on the result and the expected.

Let’s make our testing framework support promises so users can use async/await.

复制代码
const { sumAsync, subtractAsync } = require("./math");

let result, expected;

test("sum adds numbers", async () => {
  result = await sumAsync(3, 7);
  expected = 10;
  expect(result).toBe(expected);
});

test("subtract substracts numbers", async () => {
  result = await subtractAsync(7, 3);
  expected = 4;
  expect(result).toBe(expected);
});

function test(title, cb) {
  try {
    cb();
    console.log(`%c ✔︎ ${title}`, "color: green");
  } catch (err) {
    console.error(`✘ ${title}`);
    console.error(err);
  }
}

function expect(actual) {
  return {
    toBe(expected) {
      if (actual !== expected) {
        throw new Error(`${actual} is not equal to ${expected}`);
      }
    }
  };
}
复制代码

 

To fix the problem, we can make our testing lib async / await.

复制代码
async function test(title, cb) {
  try {
    await cb();
    console.log(`%c ✔︎ ${title}`, "color: green");
  } catch (err) {
    console.error(`✘ ${title}`);
    console.error(err);
  }
}
复制代码

Not it works normal again.

 

These testing utilities that we built are pretty useful. We want to be able to use them throughout our application in every single one of our test files.

Some testing frameworks provide their helpers as global variables. Let’s implement this functionality to make it easier to use our testing framework and assertion library. We can do this by exposing our test and expect functions on the global object available throughout the application.

setup-global.js:

复制代码
async function test(title, cb) {
  try {
    await cb();
    console.log(`%c ✔︎ ${title}`, "color: green");
  } catch (err) {
    console.error(`✘ ${title}`);
    console.error(err);
  }
}

function expect(actual) {
  return {
    toBe(expected) {
      if (actual !== expected) {
        throw new Error(`${actual} is not equal to ${expected}`);
      }
    }
  };
}

global.test = test;
global.expect = expect;
复制代码

Run:

node --require ./setup-global.js src/index.js

 

Up to this point we’ve created all our own utilities. As it turns out, the utilities we’ve created mirror the utilities provided by Jest perfectly! Let’s install Jest and use it to run our test!

npx jest

 

posted @   Zhentiw  阅读(638)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2016-10-25 [Debug] Chrome Devtools: Elements - Console Integration
2016-10-25 [Flexbox] Use Flex to Scale Background Image
点击右上角即可分享
微信分享提示