Typescript fp ts和jest:选项的人体工程学测试,以及其中之一?

Typescript fp ts和jest:选项的人体工程学测试,以及其中之一?,typescript,testing,jestjs,fp-ts,Typescript,Testing,Jestjs,Fp Ts,我使用的是fp ts,我用Jest编写单元测试。在许多情况下,我正在测试可为空的结果,通常用选项或选项(通常是数组finds)表示。如果结果为“无”(以选项为例),并且继续知道这个结果是有的,那么让测试失败的最符合人体工程学的方法是什么 下面是我目前如何解决这个问题的一个例子: function someFunc(input: string): Option.Option<string> { return Option.some(input); } describe(`Some

我使用的是
fp ts
,我用Jest编写单元测试。在许多情况下,我正在测试可为空的结果,通常用
选项
选项
(通常是数组
find
s)表示。如果结果为“无”(以
选项
为例),并且继续知道这个结果是有的,那么让测试失败的最符合人体工程学的方法是什么

下面是我目前如何解决这个问题的一个例子:

function someFunc(input: string): Option.Option<string> {
  return Option.some(input);
}

describe(`Some suite`, () => {
  it(`should do something with a "some" result`, () => {
    const result = someFunc('abcd');

    // This is a fail case, here I'm expecting result to be Some
    if(Option.isNone(result)) {
      expect(Option.isSome(result)).toEqual(true);
      return;
    }

    expect(result.value).toEqual('abcd');
  });
});
但缺点是我必须重写
某些
的类型。在许多情况下,必须编写它是很繁重的,需要编写和导出接口来进行测试(这也不符合人体工程学)

有没有办法简化这种测试

编辑:下面是一个更接近实际情况的测试用例:


interface SomeComplexType {
  id: string,
  inputAsArray: string[],
  input: string;
}

function someFunc(input: string): Option.Option<SomeComplexType> {
  return Option.some({
    id: '5',
    inputAsArray: input.split(''),
    input,
  });
}

describe(`Some suite`, () => {
  it(`should do something with a "some" result`, () => {
    const result = someFunc('abcd');

    // This is the un-ergonomic step
    if(Option.isNone(result)) {
      expect(Option.isSome(result)).toEqual(true);
      return;
    }

    // Ideally, I would only need this:
    expect(Option.isSome(result)).toEqual(true);
    // Since nothing will be ran after it if the result is not "some"
    // But I can imagine it's unlikely that TS could figure that out from Jest expects

    // Since I now have the value's actual type, I can do a lot with it
    // I don't have to check it for nullability, and I don't have to write its type
    const myValue = result.value;

    expect(myValue.inputAsArray).toEqual(expect.arrayContaining(['a', 'b', 'c', 'd']));

    const someOtherThing = getTheOtherThing(myValue.id);

    expect(someOtherThing).toMatchObject({
      another: 'thing',
    });
  });
});

接口SomeComplexType{
id:string,
inputAsArray:字符串[],
输入:字符串;
}
函数someFunc(输入:字符串):Option.Option{
返回选项({
id:'5',
inputAsArray:input.split(“”),
输入,
});
}
描述(`Some suite`,()=>{
它(`应该做一些有“一些”结果的事情',()=>{
const result=someFunc('abcd');
//这是联合国人体工程学的步骤
如果(选项.isNone(结果)){
expect(Option.isSome(result)).toEqual(true);
返回;
}
//理想情况下,我只需要:
expect(Option.isSome(result)).toEqual(true);
//因为如果结果不是“某些”,则不会运行任何程序
//但我可以想象TS不太可能从Jest的期望中发现这一点
//因为我现在有了这个值的实际类型,所以我可以用它做很多事情
//我不必检查它的可空性,也不必编写它的类型
const myValue=result.value;
expect(myValue.inputAsArray).toEqual(expect.arrayContaining(['a','b','c','d']);
const someOtherThing=getTheOtherThing(myValue.id);
期待(其他的事情)。托马乔布特({
另一个,"东西",,
});
});
});
或者怎么样?给定
选项
toNullable
返回
string | null

import { toNullable, toUndefined } from "fp-ts/lib/Option";

it(`should do something with a "some" result`, () => {
  expect(toNullable(someFunc("abcd"))).toEqual("abcd");
});

expect(Option.isSome(result)).toEqual(true)
的问题是,不能使用键入guard
isSome
来缩小
expect
的外部代码路径中的
结果
(请参见控制流分析的工作原理)

您可以使用稍微精简一点的,并将其与
fp ts
类型的防护装置相结合,例如:

import { isSome, Option } from "fp-ts/lib/Option"

function assert<T>(guard: (o: any) => o is T, o: any): asserts o is T {
  if (!guard(o)) throw new Error() // or add param for custom error
}

it(`a test`, () => {
  const result: Option<string> = {...}
  assert(isSome, result)
  // result is narrowed to type "Some" here
  expect(result.value).toEqual('abcd');
});
从“fp ts/lib/Option”导入{isSome,Option}
函数断言(guard:(o:any)=>o是T,o:any):断言o是T{
如果(!guard(o))抛出新错误()//或为自定义错误添加参数
}
它(`a test`,()=>{
常量结果:选项={…}
断言(是一些,结果)
//这里的结果被缩小到“Some”类型
expect(result.value).toEqual('abcd');
});
我不知道是否有一种很好的方法可以用类型保护签名来增强Jest
expect
函数类型本身,但我怀疑它可以简化您的案例,而不是简单的断言或以上解决方案。

或者如何?给定
选项
toNullable
返回
string | null

import { toNullable, toUndefined } from "fp-ts/lib/Option";

it(`should do something with a "some" result`, () => {
  expect(toNullable(someFunc("abcd"))).toEqual("abcd");
});

expect(Option.isSome(result)).toEqual(true)
的问题是,不能使用键入guard
isSome
来缩小
expect
的外部代码路径中的
结果
(请参见控制流分析的工作原理)

您可以使用稍微精简一点的,并将其与
fp ts
类型的防护装置相结合,例如:

import { isSome, Option } from "fp-ts/lib/Option"

function assert<T>(guard: (o: any) => o is T, o: any): asserts o is T {
  if (!guard(o)) throw new Error() // or add param for custom error
}

it(`a test`, () => {
  const result: Option<string> = {...}
  assert(isSome, result)
  // result is narrowed to type "Some" here
  expect(result.value).toEqual('abcd');
});
从“fp ts/lib/Option”导入{isSome,Option}
函数断言(guard:(o:any)=>o是T,o:any):断言o是T{
如果(!guard(o))抛出新错误()//或为自定义错误添加参数
}
它(`a test`,()=>{
常量结果:选项={…}
断言(是一些,结果)
//这里的结果被缩小到“Some”类型
expect(result.value).toEqual('abcd');
});

我不知道是否有一种很好的方法可以用类型保护签名来增强Jest
expect
函数类型本身,但我怀疑它可以简化您的案例,而不是简单的断言或上述解决方案。

您可以从一些
编写一个不安全的转换
,例如:

函数fromSome(输入:Option.Option):T{ 如果(选项.isNone(输入)){ 抛出新错误(); } 返回input.value; }
然后在测试中使用它

it(`should do some'result`,()=>{
const result=someFunc('abcd');
const myValue=fromSome(结果);
//用我的价值做点什么
});

您可以从某些
编写不安全的转换,如下所示:

函数fromSome(输入:Option.Option):T{ 如果(选项.isNone(输入)){ 抛出新错误(); } 返回input.value; } 然后在测试中使用它

it(`should do some'result`,()=>{
const result=someFunc('abcd');
const myValue=fromSome(结果);
//用我的价值做点什么
});

这个问题在这一点上有点老了,并且有一个公认的答案,但是有两个非常好的库,可以让测试
fp ts
选项都非常愉快。它们都很好用,我真的无法决定我更喜欢哪一个

他们允许你写这样的东西:

test('some test', () => {
  expect(E.left({ code: 'invalid' })).toSubsetEqualLeft({ code: 'invalid' })
})

这个问题在这一点上有点老了,并且有一个公认的答案,但是有两个非常好的库使得测试
fp ts
选项都非常愉快。它们都很好用,我真的无法决定我更喜欢哪一个

他们允许你写这样的东西:

test('some test', () => {
  expect(E.left({ code: 'invalid' })).toSubsetEqualLeft({ code: 'invalid' })
})

我不确定我是否听懂了。什么是有效案例<代码>选项。isNone(结果)
是否为
?还是什么?我已经更新了描述,希望能让它更清楚。此测试用例假设结果应该是
some