【问题标题】:How to mock functions/methods which updates same object?如何模拟更新相同对象的函数/方法?
【发布时间】:2020-12-09 14:26:14
【问题描述】:

我在类中有 2 个方法

  1. 方法A()
  2. 方法B()

代码:

const myModule1 =  require('./foo');
const myModule2 =  require('./bar');

const obj = {
   value: 100,
   text: "Hello"
 };

const updatedObj = {
   value: 200,
   text: "Hello"
}

// Inside beforeEach block
myModule.methodA.mockReturnValue(() => obj);
myModule2.methodB.mockReturnValue(() => updatedObj);

现在 methodA 正在返回模拟对象,但我正在测试的类同时使用 methodB 和 methodA。现在 methodB 正在更新 methodA 返回的相同模拟对象,并将 obj.value 从 100 更新为 200。

如果我使用 updatedObj,下面的代码将毫无意义,因为在这种情况下,测试的意义何在。 expect(updatedObj.value).toEqual(200) ---> 这样的测试没有意义

我该如何做这样的事情: @ 987654323@ 假设我正在模拟方法B 的返回值,它更新返回相同模拟对象的相同对象。我怎样才能做到这一点?

所以基本上我想同时模拟 methodA 和 methodB 但是如何使用相同的对象而不是使用两个不同的对象是可能的吗?

【问题讨论】:

  • 我不确定你在问什么。如果您单独测试methodAmethodB,您不会嘲笑它们。如果methodA 使用methodB 并且您正在测试methodA,您将不会模拟methodA。如果您正在测试使用methodAmethodBmethodC,但methodB 依赖于methodA 的结果,则您不会模拟methodB,因为您会重复逻辑,并且会运行失去同步的风险。这是依赖副作用的危险之一,尤其是嵌套副作用。

标签: javascript unit-testing jestjs


【解决方案1】:

你的理解是有缺陷的。您不测试模拟对象。您假设这些按预期工作。您想测试使用这些对象的代码。

你用模拟做的事情是:

  1. 检查使用模拟对象的函数的结果(即不考虑模拟状态,只提供返回该特定示例的正确值的模拟)
  2. 您可以验证调用,因此您可以确定对methodA 的调用是使用正确的参数完成的。

换句话说,您不检查 obj.value 是否已更改为 200,而是检查 methodA 是否使用正确的参数调用(这样实际实现会修改对象以将参数设置为 200 )。

您可以look at Jest documentation 显示如何获取对模拟函数的调用,因此您必须对 调用 做出断言,而不是函数的实际实现会执行的操作已经表演了。

所以如果myModule.methodA 是一个模拟函数,您将检查:

expect(myModule.methodA.mock.calls).toEqual([[200]])

这将测试代码使用200 的参数对methodA 进行了一次调用。 真正的methodA 是否会修改obj 是一个无关紧要的实现细节。

(您没有显示methodAB 的参数,所以显然这会根据调用方式而改变。


这就是说,请注意单元测试试图隔离系统的不同部分,为此我们使用模拟。但是,进行 集成 测试也非常有用。基本上只需运行methodA 即可真正使用内存数据库或网络服务器来代替真实的东西。

在这种情况下,检查obj 的值是否更改为200 应该是集成测试的一部分,而不是使用methodA/B 模拟版本的代码的单元测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-08
    • 2013-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    相关资源
    最近更新 更多