Jest中预期结果的逻辑OR

时间:2017-06-20 13:18:16

标签: javascript jestjs

这将是示例中最好的解释

expected(someNumber).toBe(1).or.toBe(-2).or.toBe(22) // expect result is 1 or -2 or 22

这是一个糟糕的语法,但是可以像开玩笑那样做吗?

6 个答案:

答案 0 :(得分:6)

如果确实需要做到这一点,我想你可以将逻辑比较放在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分别是预期值)。在上述情况中,expect调用中提供的实际值(不恰当),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的更多详细信息,则很难对此进行评论。

答案 1 :(得分:4)

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

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

要使其更加方便和易读,您可以将其放入帮助函数中:

function expect_or(...tests) {
  try {
    tests.shift()();
  } catch(e) {
    if (tests.length) expect_or(...tests);
    else throw e;
  }
}

并像这样使用它:

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

我也在寻找expect.oneOf问题的解决方案。您可能要结帐d4nyll's solution

这是它如何工作的一个例子。

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

答案 4 :(得分:1)

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

TypeScript中的示例

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])
    });
  });
});

答案 5 :(得分:0)

我建议使用.toContain(item)匹配器。可以在here中找到该文档。

下面的代码应该可以正常工作:

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