深入了解模拟和存根:提高单元测试质量的关键技术

一、引言

在进行单元测试时,我们经常会遇到对外部资源的依赖,如数据库、网络接口等。模拟(Mocking)和存根(Stubbing)是两种帮助我们模拟这些外部资源,使我们能够在隔离环境中测试单元的方法。在本文中,我们将详细介绍模拟和存根,以及如何在单元测试中使用它们。

二、模拟和存根是什么?

模拟和存根都是用来模拟外部资源的技术,但它们的关注点略有不同:

  1. 存根(Stubs):存根是用来提供预设行为的。它们在你调用方法时返回一个特定的值或抛出一个异常。

  2. 模拟(Mocks):模拟不仅提供预设行为,还能检查调用的次数、参数等。通常我们用模拟来验证一个对象是否正确地使用了另一个对象。

三、使用模拟和存根的例子

下面,我们将使用JavaScript中的流行测试库,Jest,来展示如何使用模拟和存根。

例1:使用存根

假设你有一个函数getUserName,它从数据库中获取用户的名字。你想要测试这个函数,但是不想依赖真实的数据库。

async function getUserName(userId) {
  const user = await db.getUser(userId);
  return user.name;
}

你可以使用Jest的jest.fn()方法来创建一个存根:

const db = {
  getUser: jest.fn()
};

db.getUser.mockResolvedValue({ name: 'Alice' });

expect(await getUserName(1)).toBe('Alice');

在这个例子中,我们创建了一个存根来代替db.getUser方法。这个存根总是返回一个具有名字"Alice"的用户。

例2:使用模拟

假设你有一个login函数,它调用了一个authentication服务来验证用户的凭据。你想要测试这个函数,但是你更关心它是否正确地调用了authentication服务。

async function login(username, password) {
  return await authentication.authenticate(username, password);
}

你可以使用Jest的jest.fn()方法来创建一个模拟:

const authentication = {
  authenticate: jest.fn()
};

authentication.authenticate.mockResolvedValue(true);

await login('Alice', 'password');

expect(authentication.authenticate).toHaveBeenCalledWith('Alice', 'password');

在这个例子中,我们创建了一个模拟来代替authentication.authenticate方法。然后,我们使用toHaveBeenCalledWith方法来验证login函数是否正确地调用了authentication.authenticate方法。

四、结论

模拟和存根是单元测试中的重要工具。它们帮助我们创建隔离的测试环境,使我们能够集中测试代码的特定部分,而不必担心其他外部依赖项。

下面是一些更深入使用模拟和存根的示例:

例3:更复杂的存根行为

在有些情况下,你可能想要模拟一些更复杂的行为,例如抛出异常。你可以通过配置存根来实现这一点。

const db = {
  getUser: jest.fn()
};

db.getUser.mockRejectedValue(new Error('User not found'));

try {
  await getUserName(1);
} catch (e) {
  expect(e.message).toBe('User not found');
}

在这个例子中,我们配置存根在被调用时抛出一个错误。然后,我们在测试中捕获这个错误,并验证它的消息是否正确。

例4:模拟函数调用的次数

除了验证模拟函数是否被正确的参数调用,你还可以验证模拟函数被调用的次数。

const authentication = {
  authenticate: jest.fn()
};

authentication.authenticate.mockResolvedValue(true);

await login('Alice', 'password');
await login('Bob', 'password');

expect(authentication.authenticate).toHaveBeenCalledTimes(2);

在这个例子中,我们使用toHaveBeenCalledTimes方法来验证login函数是否调用了两次authentication.authenticate方法。

五、结语

模拟和存根是一种强大的工具,可以帮助你编写出更加健壮和可维护的单元测试。通过了解何时以及如何使用这些工具,你可以更有效地测试你的代码,而无需担心外部依赖的复杂性。希望以上的示例可以帮助你在实践中更好地理解和应用模拟和存根。

六、参考链接

  • Jest: https://jestjs.io/

  • Sinon (另一款支持存根和模拟的JavaScript测试库): http://sinonjs.org/

后:下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

整套资料获取

猜你喜欢

转载自blog.csdn.net/wx17343624830/article/details/131245285
今日推荐