【问题标题】:In unit testing, how to test a function having object parameters?在单元测试中,如何测试具有对象参数的函数?
【发布时间】:2018-12-07 07:55:06
【问题描述】:

进行单元测试时,是否必须发送完整的真实对象参数? 或者您只是发送一个包含函数所需属性的对象参数?

例如,这是一个需要单元测试的示例函数:

    function ChangeName(person) {
      if (person !== null) {
        let {firstName} = person.firstName;
        firstName = firstName + '_firstName';
        person.firstName = firstName;
        return person;
      }
      return person;
    }

这是一个发送完整对象的示例测试:

    expect(
      ChangeName(
        {
          firstName: 'Juan', 
          lastName: 'dela Cruz', 
          age: 22, 
          gender: 'Male', 
          aboutMe: 'About_Me', 
          schools:[
            {id: 1, name: 'School Name 1'},
            {id: 1, name: 'School Name 1'},
            {id: 1, name: 'School Name 1'},
            {id: 1, name: 'School Name 1'}
          ]
        }
      )
    ).toEqual(
      {
        firstName: 'Juan_firstName', 
        lastName: 'dela Cruz', 
        age: 22, 
        gender: 'Male', 
        aboutMe: 'About_Me', 
        schools:[
          {id: 1, name: 'School Name 1'},
          {id: 1, name: 'School Name 1'},
          {id: 1, name: 'School Name 1'},
          {id: 1, name: 'School Name 1'}
        ]
      }
    );

这是一个示例测试发送一个对象,该对象具有仅在函数中需要的属性(包括姓氏,仅用于示例):

    expect(
      ChangeName(
        {
          firstName: 'Juan', 
          lastName: 'dela Cruz', 
        }
      )
    ).toEqual(
      {
        firstName: 'Juan_firstName', 
        lastName: 'dela Cruz', 
      }
    );

【问题讨论】:

  • 可以使用Sinon.js等模拟框架模拟对象

标签: javascript reactjs unit-testing testing jestjs


【解决方案1】:

我只提供我测试所需的代码。

在你的情况下,这意味着:

expect(changeName({ 
    firstName: 'Juan',
    lastName: 'dela Cruz'
}).toEqual({ 
    firstName: 'Juan_firstName',
    lastName: 'dela Cruz'
});

为什么?

  • 重构 person 对象时工作量更少
  • 测试更具可读性,您只拥有测试所关心的内容
  • 通过鸭子类型和/或函数式编程,您可以在其他对象(宠物……)上重复使用此函数
  • lastName(或任何其他名称)明确表示不应更改任何其他内容

如果您使用打字(流程,打字稿),这可能会改变。


我还注意到一些可能会困扰您的错误:

let { firstName } = person;

您不必重复名字

const newPerson = {
    ...person,
    firstName: firstName + '_firstName'
}
return newPerson;

这样你就不会改变在 React 中可能有害的原始 person 对象。

【讨论】:

    【解决方案2】:

    这取决于您希望测试提供的保证。

    在您的示例中,如果您只想检查“firstName 属性已按预期更新”,则{ firstName: 'Juan' } 是传递给changeName 函数的参数的正确复杂程度。

    但是,如果您的测试需要提供的保证实际上是“firstName 属性已按预期更新,不应更改任何其他内容”,那么拥有一个完整的对象就变得很重要,代表函数预期处理的数据类型。

    如果按照您的测试示例中所示实施,后者可能更难阅读。这可以通过将对象创建放在实用程序函数中来缓解,在这种情况下,它可以像更简单的示例一样可读。

    // buildPerson() creates a new, complete 'person' object when called,
    // and overrides its properties with the provided ones
    expect(
      changeName(buildPerson({ firstName: 'Juan' }))
    ).toEqual(
      buildPerson({ firstName: 'Juan_firstName' })
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-21
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多