Jest中预期结果的逻辑OR

9bfwbjaz  于 2023-01-15  发布在  Jest
关注(0)|答案(6)|浏览(160)

这将是最好的解释在一个例子
expected(someNumber).toBe(1).or.toBe(-2).or.toBe(22) // expect result is 1 or -2 or 22
这是错误的语法,但能在开玩笑时这样做吗?

epfja78i

epfja78i1#

一个简单的解决方法是使用标准的.toContain()匹配器(https://jestjs.io/docs/en/expect#tocontainitem)并反转expect语句:

expect([1, -2, 22]).toContain(someNumber);
d4so4syb

d4so4syb2#

如果您真的需要这样做,我想您可以将逻辑比较放在expect调用中,例如:

expect(someNumber === 1 || someNumber === -2 || someNumber === 22).toBeTruthy();

如果这只是一个“快速和肮脏”的检查,这可能就足够了。
然而,正如您的问题下面的几条评论所建议的,似乎有几种“代码气味”使您的初始问题以及上面的解决方案看起来像是一种不适当的进行测试的方式。
首先,就我提出的解决方案而言,使用toBeTruthy破坏了Jasmine/Jest匹配器的使用方式。这有点像使用expect(someNumber === 42).toBeTruthy();而不是expect(someNumber).toBe(42)。Jest/Jasmine测试的结构是在expect调用中提供实际值(即expect(actualValue))和匹配器中的预期值(例如toBe(expectedValue)toBeTruthy(),其中expectedValuetrue分别为期望值)。在上述情况下,实际值为(不适当),toBeTruthy匹配器只是验证这一事实。
你可能需要分开测试。例如,你有一个函数(例如,名为yourFunction),你正在测试它提供(至少)3个不同的可能的离散输出。我会假设输出的值取决于输入的值。如果是这种情况,你可能应该分开测试所有的输入/输出组合,例如:

it('should return 1 for "input A" ', () => {
  const someNumber = yourFunction("input A");
  expect(someNumber).toBe(1);
});

it('should return -2 for "input B" ', () => {
  const someNumber = yourFunction("input B");
  expect(someNumber).toBe(-2);
});

it('should return 22 for "input C" ', () => {
  const someNumber = yourFunction("input C");
  expect(someNumber).toBe(22);
});

或者至少...

it('should return the appropriate values for the appropriate input ', () => {
  let someNumber;
  someNumber = yourFunction("input A");
  expect(someNumber).toBe(1);

  someNumber = yourFunction("input B");
  expect(someNumber).toBe(-2);

  someNumber = yourFunction("input C");
  expect(someNumber).toBe(22);
});

这样做的一个积极结果是,如果您的代码在将来发生更改,例如(但只有一个)条件发生变化(就输入 * 或 * 输出而言),您只需要更新三个较简单测试中的一个,而不是更新单个较复杂的聚集测试。此外,通过这种方式分离测试,失败的测试将更快地告诉你问题在哪里,例如“输入A”、“输入B”或“输入C”。
或者,您可能需要实际重构yourFunction,即被测代码本身。您真的希望代码中有一个特定函数根据不同的输入返回三个独立的离散值吗?也许是这样,但我会单独检查代码,看看它是否需要重写。在不了解yourFunction的更多细节的情况下,很难进一步评论这一点。

nnvyjq4y

nnvyjq4y3#

要避免将所有逻辑比较放在一条语句中并使用toBeTruthy(),可以使用嵌套的try/catch语句:

try {
  expect(someNumber).toBe(1)
}
catch{
  try {
    expect(someNumber).toBe(-2)
  }
  catch{
    expect(someNumber).toBe(22)
  }
}

为了使它更方便、更易读,你可以把它放到一个helper函数中:

function expect_or(...tests) {
  if (!tests || !Array.isArray(tests)) return;
  try {
    tests.shift()?.();
  } catch (e) {
    if (tests.length) expect_or(...tests);
    else throw e;
  }
}

注意:使用Typescript将第1行替换为function expect_or(...tests: (() => void)[]) {,以向函数参数添加类型。
像这样使用它:

expect_or(
   () => expect(someNumber).toBe(1),
   () => expect(someNumber).toBe(-2),
   () => expect(someNumber).toBe(22)
 );
fxnxkyjh

fxnxkyjh4#

正如@JrGiant建议的那样,可能有一个toBeOneOf,但是,实现自己的匹配器很容易:

  • 类型脚本中的示例 *:
expect.extend({
  toBeOneOf(received: any, items: Array<any>) {
    const pass = items.includes(received);
    const message = () =>
      `expected ${received} to be contained in array [${items}]`;
    if (pass) {
      return {
        message,
        pass: true
      };
    }
    return {
      message,
      pass: false
    };
  }
});

// Declare that jest contains toBeOneOf
// If you are not using TypeScript, remove this "declare global" altogether
declare global {
  namespace jest {
    interface Matchers<R> {
      toBeOneOf(items: Array<any>): CustomMatcherResult;
    }
  }
}

describe("arrays", () => {
  describe("getRandomItemFromArray", () => {
    it("should return one of the expected - 1", () => {
      expect(getRandomItemFromArray([1, 2])).toBeOneOf([1, 2])
    });
  });
});
ne5o7dgx

ne5o7dgx5#

我也在寻找expect.oneOf问题的解决方案。您可能想要 checkout d4nyll's solution
下面是一个它如何工作的例子。

expect(myfunction()).toBeOneOf([1, -2, 22]);
jq6vz3qz

jq6vz3qz6#

我推荐使用.toContain(item)匹配器,文档可以在这里找到。
下面的代码应该可以正常工作:

expect([1, -2, 22]).toContain(someNumber);

相关问题