使用 Typescript 创建自定义茉莉花匹配器 [英] Create custom jasmine matcher using Typescript

查看:17
本文介绍了使用 Typescript 创建自定义茉莉花匹配器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个 angular2 项目中使用 jasmine,并且在为测试编写自定义匹配器时遇到了一些麻烦.我希望能够比较两个相对复杂的对象.我发现 这篇文章声称解决了这个问题,但它只会导致打字稿错误,指出它无法识别 jasmine 的 Matchers 对象上的新方法.相关代码是这样的:

声明模块 jasmine {接口匹配器 {toBeNumeric(): 无效;}}

另一篇文章给出了一个类似但略有不同的解决方案会产生相同的错误.

声明命名空间 jasmine {接口匹配器 {toHaveText(预期:字符串):布尔值;}}

我试过了

let m: jasmine.Matchers = expect(someSpy.someMethod).toHaveBeenCalled();

得到了这个错误:

<块引用>

类型jasmine.Matchers"不可分配给类型jasmine.Matchers".存在同名的两种不同类型,但它们不相关.

这似乎表明 declare namespace jasmine 语句正在创建一个新的 jasmine 命名空间,而不是扩展现有的命名空间.

那么,我怎样才能创建自己的匹配器,让 typescript 满意呢?

解决方案

Daf 的回答主要对我有用,我只是注意到他的示例代码和他命名文件的方式存在问题.我还遇到了另一个不相关的问题.因此有了新的答案.

  • 由于某种原因,当接口文件与匹配器文件同名时,我的应用程序不喜欢它.例如 foo.ts 和 foo.d.ts.对于我的应用,它需要是 foo.ts 和 foo-interface.d.ts 或类似的东西.
  • 也不要将 foo.ts 中的接口导入 foo-interface.d.ts,它似乎也不喜欢这样.

匹配器 - custom-matchers.ts

import MatchersUtil = jasmine.MatchersUtil;导入 CustomMatcherFactories = jasmine.CustomMatcherFactories;导入 CustomEqualityTester = jasmine.CustomEqualityTester;导入 CustomMatcher = jasmine.CustomMatcher;导入 CustomMatcherResult = jasmine.CustomMatcherResult;出口 const SomeCustomMatchers: CustomMatcherFactories = {toReallyEqual: 函数 (util: MatchersUtil, customEqualityTester: CustomEqualityTester[]): CustomMatcher {返回 {比较:函数(实际:任意,预期:任意,anotherCustomArg:任意):CustomMatcherResult {//你的支票在这里.const 通过 = 实际 === 预期;//结果和消息生成.返回 {通过:通过,消息:通过?`实际等于预期`: `实际不等于预期`,}}}}};

<块引用>

注意 compare 函数可以有任意数量的自定义参数(甚至是可变参数),并且只需要/保留第一个参数(以了解实际值);但如果函数名以toHave"开头,则(而不是 toReallyEqual),那么第二个参数是为key: string"保留的.(要知道对象的字段名称,我的意思是,Jasmine2 会为我们循环).

此外,我们可以中继 Jasmine 来生成消息,例如:

message: util.buildFailureMessage('toReallyEqual', pass, actual, expected, anotherCustomArg),

接口文件 - matcher-types.d.ts - 不能与您的匹配器文件同名

声明命名空间 jasmine {接口匹配器<T>{toReallyEqual(expected: any, anotherCustomArg: any, expectFailOutput?: any): boolean;}}

自定义匹配器测试

describe('Hello', () => {beforeEach(() => {jasmine.addMatchers(SomeCustomMatchers)});it('应该允许自定义匹配器', () => {期望('foo').toReallyEqual('foo');expect('bar').not.toReallyEqual('test');})});

I'm using jasmine on an angular2 project and having some trouble writing a custom matcher for a test. I want to be able to compare two relatively complex objects. I found this article which claims to solve the issue but it simply results in a typescript error stating that it doesn't recognize the new method on jasmine's Matchers object. The relevant code is this:

declare module jasmine {
    interface Matchers {
        toBeNumeric(): void;
    }
}

Another article gives a similar, but slightly different solution that gives the same error.

declare namespace jasmine {
    interface Matchers {
        toHaveText(expected: string): boolean;
    }
}

I tried this

let m: jasmine.Matchers = expect(someSpy.someMethod).toHaveBeenCalled();

and got this error:

Type 'jasmine.Matchers' is not assignable to type 'jasmine.Matchers'. Two different types with this name exist, but they are unrelated.

That seems to indicate that the declare namespace jasmine statement is creating a new jasmine namespace rather than extending the existing one.

So how can I create my own matcher that typescript will be happy with?

解决方案

Daf's answer mostly worked for me I just noticed an issue with his sample code and the way he named his files. I also happened upon another unrelated issue. Hence a new answer.

  • For some reason my app does not like it when the interface file has the same name as the matcher file. e.g foo.ts and foo.d.ts. For my app it needed to be foo.ts and foo-interface.d.ts or something like it.
  • Also don't import interfaces from foo.ts into foo-interface.d.ts it also does not seem to like this.

Matcher - custom-matchers.ts

import MatchersUtil = jasmine.MatchersUtil;
import CustomMatcherFactories = jasmine.CustomMatcherFactories;
import CustomEqualityTester = jasmine.CustomEqualityTester;
import CustomMatcher = jasmine.CustomMatcher;
import CustomMatcherResult = jasmine.CustomMatcherResult;

export const SomeCustomMatchers: CustomMatcherFactories = {
    toReallyEqual: function (util: MatchersUtil, customEqualityTester: CustomEqualityTester[]): CustomMatcher {
        return {
            compare: function (actual: any, expected: any, anotherCustomArg: any): CustomMatcherResult {

                // Your checks here.
                const passes = actual === expected;

                // Result and message generation.
                return {
                    pass: passes,
                    message: passes ? `Actual equals expected`
                                    : `Actual does not equal expected`,
                }
            }
        }
    }
};

NOTE that compare function can have as many custom-parameters as we want (or even Variadic), and that ONLY first-argument is required/reserved (to know actual-value); but if the function name begins with "toHave" (instead of toReallyEqual), then the second argument is reserved for "key: string" (to know object's field name, I mean, Jasmine2 will loop for us).

Also, we could relay on Jasmine for message-generation, like:

message: util.buildFailureMessage('toReallyEqual', passes, actual, expected, anotherCustomArg),

Interface file - matcher-types.d.ts - cannot be the same name as your matcher file

declare namespace jasmine {
    interface Matchers<T> {
        toReallyEqual(expected: any, anotherCustomArg: any, expectationFailOutput?: any): boolean;
    }
}

Custom matcher test

describe('Hello', () => {

    beforeEach(() => {
        jasmine.addMatchers(SomeCustomMatchers)
    });

    it('should allow custom matchers', () => {
        expect('foo').toReallyEqual('foo');
        expect('bar').not.toReallyEqual('test');
    })
});

这篇关于使用 Typescript 创建自定义茉莉花匹配器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆