Jest: 测试对象、数组或字符串。

创建于 2017-05-03  ·  29评论  ·  资料来源: facebook/jest

有没有办法检查组件是对象、数组还是字符串? 这将类似于 chai 的 'should.be.a' 例如:validationResult.SSN[0].should.be.a('string')。

最有用的评论

一个简单的 toBeType 扩展,适合那些想要它的人

expect.extend({
    toBeType(received, argument) {
        const initialType = typeof received;
        const type = initialType === "object" ? Array.isArray(received) ? "array" : initialType : initialType;
        return type === argument ? {
            message: () => `expected ${received} to be type ${argument}`,
            pass: true
        } : {
            message: () => `expected ${received} to be type ${argument}`,
            pass: false
        };
    }
});

describe("testing extended expect", () => {
    it("tests normal types correctly", () => {
        expect("").toBeType("string");
        expect({}).toBeType("object");
        expect(1).toBeType("number");
    });
    it("tests array types correctly", () => {
        expect([]).toBeType("array");
    });
    it("works with promises", () => {
        expect(Promise.resolve([])).resolves.toBeType("array");
    });
});

实施起来非常简单。 真的应该在核心tbh。

注意 - 如果您将该扩展放在安装文件中,那么您希望将它放在setupTestFrameworkScriptFile不是setupFiles (因为扩展仅在前者中可用)

所有29条评论

不,没有。 您可以在此处找到所有可用匹配器的列表: https :

你也可以使用普通的 JavaScript 或者像lodash这样的辅助库:

test('name', () => {
  // array
  expect(Array.isArray(['value'])).toBe(true);
  // string
  expect(typeof 'value').toBe('string');
  // object
  expect({value: 'value'}).toBeTruthy();
  expect(typeof {value: 'value'}).toBe('object');
})

次要问题 - 这对承诺结果没有帮助。

expect(somePromise).resolves.toBe(...)此时没有办法检查类型。 如果您不在乎内容什么,而只关心它是一个字符串。 我希望expects.stringContaining("")能够解决问题,但这也行不通。

@abritinthebay我正是这种情况,这是谷歌的第一个结果,也许应该重新打开?

当然,应该多考虑一下。 我的解决方法是添加到链中,以便执行typeof部分。 例如:

expect(somePromise.then(data => typeof data)).resolves.toBe("object");

它有效,但并不完全干净。

@thymikee检查事物类型是一个足够常见的用例(通用),对于缺少它们的测试框架来说,实际上没有任何借口。 你的替代方案是不可接受的,因为我们失去了我们正在测试的所有上下文。

这个expect(Array.isArray(['value'])).toBe(false);失败了

expect(received).toBe(expected)
    Expected value to be (using ===):
      false
    Received:
      true. 

所以我们要么得到可怕的断言消息,要么我们必须扩展 Jest 来支持这些类型的检查。 对于 Jest 的维护者来说,与每个使用这些功能的人都需要自己实现它们相比,这样做一次不是更有意义吗?

然后使用expect.extend创建您自己的匹配器并将其发布为 npm 模块。 如果它流行起来,我们最终可能会将它合并到 Jest 核心中 ;)

一个简单的 toBeType 扩展,适合那些想要它的人

expect.extend({
    toBeType(received, argument) {
        const initialType = typeof received;
        const type = initialType === "object" ? Array.isArray(received) ? "array" : initialType : initialType;
        return type === argument ? {
            message: () => `expected ${received} to be type ${argument}`,
            pass: true
        } : {
            message: () => `expected ${received} to be type ${argument}`,
            pass: false
        };
    }
});

describe("testing extended expect", () => {
    it("tests normal types correctly", () => {
        expect("").toBeType("string");
        expect({}).toBeType("object");
        expect(1).toBeType("number");
    });
    it("tests array types correctly", () => {
        expect([]).toBeType("array");
    });
    it("works with promises", () => {
        expect(Promise.resolve([])).resolves.toBeType("array");
    });
});

实施起来非常简单。 真的应该在核心tbh。

注意 - 如果您将该扩展放在安装文件中,那么您希望将它放在setupTestFrameworkScriptFile不是setupFiles (因为扩展仅在前者中可用)

谢谢@abritinthebay

因此,如果人们需要,我将其封装在一个 npm 模块中:

https://www.npmjs.com/package/jest-tobetype

describe("assertion framework", ()=> {
 it("should check primitive types", () => {
   expect(expect.toBeA).toBeA("function")
  })
})

失败:expect(...).toBeA 不是函数类型错误:expect(...).toBeA 不是函数

https://github.com/jest-community/jest-extended拥有您可能想要的所有类型匹配器(我认为)。

我一直在我的测试中使用toBeInstanceOf

expect($wrapper.vm.countries).toBeInstanceOf(Array);

然后使用 expect.extend 创建您自己的匹配器并作为 npm 模块发布。 如果它流行起来,我们最终可能会将它合并到 Jest 核心中 ;)

是的,并且可能会在您编写自己的 Jest 框架时编写它。

这个可能是你在 GitHub 上得到的最糟糕的答案中的佼佼者。

所以@abritinthebay完全符合@thymikee 的要求(这远远超过标准的拉取请求)。

既然那个勇敢的灵魂完成了所有的工作,我们其他人什么时候才能最终获得这个匹配器(无需安装另一个库)? 维护人员是否仍在推动这不属于 Jest 的想法,或者这只是从他们的视线中消失了?

我们对使其成为核心的内容非常严格,通常不会添加糖匹配器。 Jest 核心是一个相当大的架构,我们添加的每个匹配器都会增加维护成本

对于糖,我们一般推荐https://github.com/jest-community/jest-extended

一个人的糖是另一个人的(或者在这种情况下,至少是其他七个人的)真正有用和合乎逻辑的特性,属于核心库。

显然,作为维护者,您的投票胜过我们所有人的投票,您有各种各样的担忧,我们没有,所以我完全尊重这一点。 但我只是想请您看看为什么这里的每个人都认为此功能属于核心库(如此强烈以至于一个人跳过了多个圈子为您编写代码)。 这里有一个需求,如果你忽略它 Jest核心库用户(老实说,他们中的 90% 甚至永远不会听说 jest-extended)将会失败。

.to.be.an.instanceOf不会是多少用户认为检查类型,因此对于这些用户,即使您将其视为糖,您也实际上拒绝了他们在没有额外库的情况下在 Jest 中检查类型的能力。

是的,我听到了。 明确地说,“糖”是指旨在使事情更易于阅读或表达的语法。 糖,根据定义,是已经存在的特征的变体

在这种情况下,我们有:

// Supported
expect(typeof foo).toBe('string');

// Proposed Sugar
expect(foo).toBeType('string');

所以并不是我们不支持检查类型。 我们的确是。 我们支持第一种选择。 此选项使用核心toBe匹配器,我们花了很多时间修复其中的错误并调整消息,以便用户获得良好的体验

Jest-extended 中有近 60 个匹配器,其中许多是纯糖。 对于这些匹配器中的任何一个,您可能会发现至少有 7 个其他人发现它们非常有用,因此如果这是我们用于添加到核心的启发式方法,我们可能会将所有时间都花在维护匹配器上

公平地说 - 大多数匹配器在某种程度上都是“糖”。 我的意思是toBeGreaterThanOrEqual只是expect(foo >= bar).toBe(true);

匹配器实际上是_几乎所有_布尔语句周围的糖;)

(我说这不是为了挖掘,只是为了指出它是......一条非常模糊的线)

正如 abritinthebay 所建议的,这并不是真正关于糖,而是关于“必要”和“不必要”(对于核心库)糖。 在这个线程中有很多人说“嘿,能够检查所有类型应该是测试库的核心”(即,这是必要的)。

听我们说或不听,作为维护者,您还有很多其他问题。 但我不认为正确的回应是说“你的糖本质上是不必要的糖”(这是我试图解释你,而不是试图把话放在你嘴里)当它不是固有的:它是 100% 你的电话是否 Jest可以检查所有类型或不开箱即用。

怎么样,是不是很难:P?

expect(Array.isArray(['your', 'array'])).toBe(true);

expect(typeof something === "object").toBe(true); 
// - or -
expect(something instanceof Object).toBe(true);

expect(typeof something === "string").toBe(true); 

@nahumzs虽然它有效,但问题是在您的测试输出失败时,它会说“预期假为真”,这不是很有帮助;)

我认为这是要走的路:)

describe('type check', () => {
    test('should be type string', () => {
        expect(typeof '').toBe('string')
    })

    test('should be type number', () => {
        expect(typeof 10).toBe('number')
    })

    test('should be type boolean', () => {
        expect(typeof true).toBe('boolean')
    })

    test('should be type undefined', () => {
        expect(typeof undefined).toBe('undefined')
    })

    test('should be type object', () => {
        expect(typeof { foo: 'bar' }).toBe('object')
    })

    test('should be type function', () => {
        expect(typeof function() {}).toBe('function')
    })

    test('should be type null', () => {
        expect(typeof null).toBe('object')
    })
})

我重构了@abritinthebay 提供的实现。 对我来说似乎有点舒服。

```javascript
期望.扩展({
/ ** @param { } 收到
* @param {string|string[]} 参数
* @return {{pass:boolean,message:(function():string)}}
*/
toBeType(收到,arg){
const isCorrectType = arg => {
const receivedType = typeof 收到;

        const checkForSingle = arg => {
            const type = receivedType === 'object'
                ? Array.isArray(received)
                    ? 'array'
                    : receivedType
                : receivedType;

            return type === arg;
        };

        const checkForArr = arg => {
            const reducer = (prev, curr) => prev || isCorrectType(curr).isCorrect;

            return arg.reduce(reducer, false);
        };

        return {
            receivedType,
            isCorrect: Array.isArray(arg)
                ? checkForArr(arg)
                : checkForSingle(arg)
        };
    };

    const {isCorrect, receivedType} = isCorrectType(arg);

    return {
        pass: isCorrect,
        message: () => {
            const toBe = Array.isArray(arg)
                ? arg.join(`' or '`)
                : arg;

            return `Expected '${received}' of '${receivedType}' type to be of '${toBe}' type(s)`;
        }
    };
}

});

你应该看看我的模块(上面链接)。 它的作用远不止于此。 但如果这对你有用:使用它!

我认为这是要走的路:)

describe('type check', () => {
    test('should be type string', () => {
        expect(typeof '').toBe('string')
    })

    test('should be type number', () => {
        expect(typeof 10).toBe('number')
    })

    test('should be type boolean', () => {
        expect(typeof true).toBe('boolean')
    })

    test('should be type undefined', () => {
        expect(typeof undefined).toBe('undefined')
    })

    test('should be type object', () => {
        expect(typeof { foo: 'bar' }).toBe('object')
    })

    test('should be type function', () => {
        expect(typeof function() {}).toBe('function')
    })

    test('should be type null', () => {
        expect(typeof null).toBe('object')
    })
})

它就像一种魅力,并且在未来更具可读性和可维护性。

我认为这是要走的路:)

describe('type check', () => {
    test('should be type string', () => {
        expect(typeof '').toBe('string')
    })

    test('should be type number', () => {
        expect(typeof 10).toBe('number')
    })

    test('should be type boolean', () => {
        expect(typeof true).toBe('boolean')
    })

    test('should be type undefined', () => {
        expect(typeof undefined).toBe('undefined')
    })

    test('should be type object', () => {
        expect(typeof { foo: 'bar' }).toBe('object')
    })

    test('should be type function', () => {
        expect(typeof function() {}).toBe('function')
    })

    test('should be type null', () => {
        expect(typeof null).toBe('object')
    })
})
    test('should be type object', () => {
        expect(typeof { foo: 'bar' }).toBe('object')
        // passes
        expect(typeof ['foo', 'bar']).toBe('object')
        // passes
        expect(typeof null).toBe('object')
    })

😞

这就是为什么我在上面建议我的插件:处理这个。

InstanceOf 稍微好一些,但容易出现类似的问题。

链接到它:

https://www.npmjs.com/package/jest-tobetype

感谢您的解决方案@abritinthebay

另一种解决方案:

expect('example').toEqual(expect.any(String));
expect(123).toEqual(expect.any(String));

第二个会失败:

    Expected: Any<String>
    Received: 123
此页面是否有帮助?
0 / 5 - 0 等级