【问题标题】:Using partial shape for unit testing with typescript通过 typescript 使用部分形状进行单元测试
【发布时间】:2016-09-18 06:02:55
【问题描述】:

假设我想在 typescript 中对一个函数进行单元测试。 此函数使用具有复杂形状的“选项”类型(对象)参数。

interface option {
  param1 : string
  param2 : number
  param3 : { 
    param4 : string
    param5 : boolean
    }
  .
  .
  .
  param15 : string
}

const functionToTest = (opt:option)=>{
   ...do stuff with option
}

现在假设我想编写一个单元测试,在 param1 更改时模拟 functionToTest 的正确行为,忽略对结果没有影响的其他参数。

我的理解是,为了让我的测试更有弹性,我可以用纯 JS 编写

const option1 = {
  param1 : "foo"
}

做我的测试

expect(functionToTest(option1)).to.be.true;

但是,如果我使用 typescript 编写测试,我将不得不编写一个包含所有接口(虚拟)成员的完整 option1 对象,尽管大多数会被忽略,它会使读者偏离真正的目标测试。

是否有解决方法或我应该改变我的想法?

【问题讨论】:

    标签: unit-testing typescript


    【解决方案1】:

    为此,您可以利用 typescript 的 Partial

    interface YourInterface {
      prop: string;
      foo: number;
    }
    
    const data: Partial<YourInterface> = {   
       prop: 'value'
    };
    
    // service is an instance of SomeService
    service.sendData(<YourInterface> data);
    
    
    class SomeService {
      sendData(data: YourInterface) {
    
      }
    }
    
    

    【讨论】:

    • 我不知道这将如何工作,因为您正在使用 Partial 创建一个新接口,问题在于使用现有类,但属性较少。 TS 编译器只会抱怨您缺少属性。
    • 你试过了吗?这正是 Partial 所做的事情以及创建它的原因。
    • 但是然后你使用&lt;YourInterface&gt; datatype assert 它又回到YourInterface,所以你还不如从const data = { ... } as YourInterface 开始。
    【解决方案2】:

    在我的测试中,我使用as 类型断言将部分对象传递给函数。

    const options = {
       param1: 'param1',
       param2: 22 
    } as Option;
    
    expect(functionToTest(options)).to.be.true;
    

    【讨论】:

    • 好主意,这样您就可以清楚地知道要替换的内容。
    【解决方案3】:

    您可以将参数声明为可选。

       interface option {
        param1 : string
        param2? : number
        param3? : { 
           param4 : string
           param5 : boolean
        }
        .
       param15? : string
     }
    
    
     
    

    【讨论】:

    • 是的,我曾考虑过这一点,但是在多种情况下,参数对于完整(集成)软件的正确工作不是可选的,但对于单元测试的一小部分没有用示例:假设我有一个 redux 存储,我已经用完整的数据树定义了一个状态接口,我想对一个查询状态的函数进行单元测试,对于单元测试它不会打扰整个状态树(而且我不想为每个状态写一个完整的虚拟状态对象),只是他要过滤的部分这是否意味着我应该为每个函数编写一个自定义类型?
    • 是的,我想是的,你必须为每个函数编写自定义类型,虽然你也可以在函数中声明它,你不必为此编写单独的接口,如果那是你的担心,所以你可以使用 function hello(param: { param1: string, param2: number }) 希望这会有所帮助!
    • @VincentJ 我同意你的观点,我们从不想让我们的类道具成为可选的,只是为了对它们进行单元测试,这太荒谬了。
    猜你喜欢
    • 2015-09-16
    • 2015-09-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 2018-07-26
    • 2017-01-22
    • 1970-01-01
    • 2017-06-21
    相关资源
    最近更新 更多