Jest: Testen Sie, ob Objekt, Array oder String.

Erstellt am 3. Mai 2017  ·  29Kommentare  ·  Quelle: facebook/jest

Gibt es eine Möglichkeit zu überprüfen, ob eine Komponente ein Objekt, ein Array oder ein String ist? Dies wäre ähnlich wie 'should.be.a' von chai Bsp.: ValidierungResult.SSN[0].should.be.a('string').

Hilfreichster Kommentar

Eine einfache toBeType-Erweiterung für diejenigen, die es wollen

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

Ziemlich einfach zu implementieren. Sollte wirklich im Kern sein tbh.

Hinweis - Wenn Sie dieses Extend in Ihre Setup-Dateien einfügen, möchten Sie es in setupTestFrameworkScriptFile NICHT setupFiles (da Extend nur in ersterem verfügbar ist)

Alle 29 Kommentare

Nein, gibt es nicht. Die Liste aller verfügbaren Matcher findet ihr hier: https://facebook.github.io/jest/docs/en/expect.html

Sie können dafür auch einfaches JavaScript oder eine Hilfsbibliothek wie 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');
})

Kleiner Punkt - das hilft nicht bei versprochenen Ergebnissen.

expect(somePromise).resolves.toBe(...) An dieser Stelle gibt es keine Möglichkeit, den Typ zu überprüfen. Wenn es Ihnen egal ist, was der Inhalt ist, sondern nur, dass es sich um eine Zeichenfolge handelt. Ich habe gehofft, dass expects.stringContaining("") ein Workaround ist, aber das funktioniert auch nicht.

@abritinthebay Ich bin genau in dieser Situation und dies ist das erste Ergebnis in Google, vielleicht sollte dies wieder geöffnet werden?

Es sollte auf jeden Fall ein bisschen mehr darüber nachgedacht werden. Meine Problemumgehung bestand darin, die Kette so zu ergänzen, dass der Teil typeof erledigt wird. z.B:

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

es funktioniert, aber es ist nicht gerade sauber.

@thymikee Das Überprüfen von Arten von Dingen ist ein häufiger Anwendungsfall (universal), dass es keine Entschuldigung für ein Test-Framework gibt, dem sie fehlen. Ihre Alternativen sind inakzeptabel, da wir den gesamten Kontext dessen, was wir testen, verlieren.

Dieses expect(Array.isArray(['value'])).toBe(false); schlägt fehl mit

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

Also bekommen wir entweder schreckliche Behauptungsnachrichten oder wir müssen Jest erweitern, um diese Art von Überprüfungen zu unterstützen. Ist es für die Betreuer von Jest nicht sinnvoller, dies einmal zu tun, anstatt dass jede Person, die diese Funktionen verwendet, diese Funktionen selbst implementieren muss?

Erstelle dann deine eigenen Matcher mit expect.extend und veröffentliche sie als npm-Modul. Wenn es populär wird, können wir es irgendwann mit dem Kern von Jest zusammenführen ;)

Eine einfache toBeType-Erweiterung für diejenigen, die es wollen

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

Ziemlich einfach zu implementieren. Sollte wirklich im Kern sein tbh.

Hinweis - Wenn Sie dieses Extend in Ihre Setup-Dateien einfügen, möchten Sie es in setupTestFrameworkScriptFile NICHT setupFiles (da Extend nur in ersterem verfügbar ist)

Danke @abritinthebay

Also habe ich das in ein npm-Modul verpackt, wenn die Leute es wollen:

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

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

Fehlgeschlagen: Expect(...).toBeA ist keine FunktionTypeError: Expect(...).toBeA ist keine Funktion

https://github.com/jest-community/jest-extended hat alle Typ-Matcher, die man sich wünschen kann (glaube ich).

Ich habe toBeInstanceOf in meinen Tests verwendet:

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

Erstellen Sie dann Ihre eigenen Matcher mit Expect.extend und veröffentlichen Sie diese als npm-Modul. Wenn es populär wird, können wir es irgendwann mit dem Kern von Jest zusammenführen ;)

Ja, und vielleicht schreiben Sie Ihr eigenes Scherz-Framework, wenn Sie schon dabei sind.

Diese könnte die schlechtesten Antworten, die Sie auf GitHub erhalten können, übertreffen.

Also hat @abritinthebay genau das getan @thymikee angefordert wurde (was weit mehr war als der Standard-Pull-Request).

Nun, da diese tapfere Seele die ganze Arbeit geleistet hat, wann können wir den Rest von uns endlich diesen Matcher bekommen (ohne noch eine weitere Bibliothek installieren zu müssen)? Verdrängen die Betreuer immer noch die Idee, dass dies nicht in Jest gehört, oder ist das einfach von ihrem Radar verschwunden?

Wir sind ziemlich streng mit dem, was es zum Kern macht, und fügen normalerweise keine Zucker-Matcher hinzu. Jest Core ist eine ziemlich große Architektur und jeder Matcher, den wir hinzufügen, erhöht die Wartungskosten

Für Zucker empfehlen wir generell https://github.com/jest-community/jest-extended

Der Zucker eines Mannes ist das wirklich nützliche und logische Feature eines anderen Mannes (oder in diesem Fall mindestens sieben anderer Leute), das in die Kernbibliothek gehört.

Offensichtlich übertrumpft Ihre Stimme als Betreuer alle unsere, und Sie haben alle möglichen Bedenken, die wir nicht haben, also respektiere ich das voll und ganz. Aber ich möchte Sie nur bitten, sich anzusehen, warum jeder hier der Meinung ist, dass dieses Feature in die Kernbibliothek gehört (so stark, dass eine Person durch mehrere Reifen gesprungen ist, um den Code für Sie zu schreiben). Es gibt eine Notwendigkeit , hier, und wenn Sie es Jest Kernbibliothek Benutzer ignorieren (und seien wir ehrlich, 90% von ihnen werden nicht einmal hören über Scherz-extended) wird verlieren.

.to.be.an.instanceOf wird nicht so sein, wie viele Benutzer denken, Typen zu überprüfen, also verweigern Sie diesen Benutzern, selbst wenn Sie es als Zucker betrachten, effektiv die Möglichkeit, Typen in Jest ohne eine zusätzliche Bibliothek zu überprüfen.

Ja, ich höre dich. Um es klar zu sagen, mit "Zucker" meinte ich eine Syntax, die entworfen wurde, um Dinge leichter zu lesen oder auszudrücken . Zucker ist per Definition eine Variation eines bereits vorhandenen Merkmals

In diesem Fall haben wir:

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

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

Es ist also nicht so, dass wir Prüftypen nicht unterstützen. Wir tun. Wir unterstützen die erste Option. Diese Option verwendet den zentralen toBe Matcher, in den wir viel Zeit investiert haben, um die Fehler zu beheben und die Nachricht zu optimieren, damit die Benutzer eine gute Erfahrung haben

Es gibt fast 60 Matcher in jest-extended und viele davon sind reiner Zucker. Für jeden dieser Matcher könnten Sie wahrscheinlich mindestens 7 andere Leute finden, die sie wirklich nützlich finden. Wenn das also die Heuristik wäre, die wir zum Hinzufügen zum Kern verwendet haben, würden wir wahrscheinlich unsere ganze Zeit damit verbringen, Matcher zu pflegen

Um ganz fair zu sein - die meisten Matcher sind in gewisser Weise "Zucker". Ich meine, toBeGreaterThanOrEqual ist nur Zucker für expect(foo >= bar).toBe(true);

Matcher sind wirklich _fast alles_ Zucker um boolesche Aussagen ;)

(Ich sage dies nicht, um zu graben, nur um darauf hinzuweisen, dass es ... eine sehr verschwommene Linie ist)

Wie abritinthebay vorgeschlagen hat, geht es nicht wirklich um Zucker, sondern um "notwendigen" und "unnötigen" (für die Kernbibliothek) Zucker. Sie haben eine Menge Leute in diesem Thread, die sagen: "Hey, in der Lage zu sein, alle Typen zu überprüfen, ist etwas, das zum Kern einer Testbibliothek gehören sollte" (dh es ist notwendig).

Hören Sie auf uns oder nicht, auch hier haben Sie als Betreuer viele andere Sorgen. Aber ich glaube nicht, dass die richtige Antwort darin besteht, zu sagen "Ihre ist von Natur aus unnötiger Zucker" (das versuche ich, Sie zu paraphrasieren, nicht zu versuchen, Ihnen Worte in den Mund zu legen), wenn es nicht inhärent ist: Es ist zu 100% Ihre Entscheidung, ob Jest kann alle Typen überprüfen oder nicht aus der Box.

Was ist, ist das nicht schwer :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 Während es funktioniert, besteht das Problem darin, dass auf Ihrer Testausgabe beim angezeigt wird, was nicht sehr hilfreich ist;)

Ich denke, das ist der richtige Weg :)

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')
    })
})

Ich habe die von @abritinthebay bereitgestellte Implementierung umgestaltet. Es scheint mir ein bisschen angenehm, damit zu arbeiten.

```javascript
erwarten.erweitern({
/ ** @param { } erhalten
* @param {string|string[]} arg
* @return {{pass:boolean,message:(function():string)}}
*/
toBeType(empfangen, Argument) {
const isCorrectType = arg => {
const ReceivedType = empfangener Typ;

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

});

Sie sollten sich mein Modul (oben verlinkt) ansehen. Es tut ein bisschen mehr. Aber wenn das für Sie funktioniert: Nutzen Sie es!

Ich denke, das ist der richtige Weg :)

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')
    })
})

Es funktioniert wie ein Zauber sowie besser lesbar und wartbar für die Zukunft.

Ich denke, das ist der richtige Weg :)

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')
    })

😞

Deshalb schlage ich mein obiges Addon vor: kümmert sich darum.

InstanceOf ist etwas besser, aber anfällig für ähnliche Probleme.

Link dazu:

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

Danke für die Lösung @abritinthebay

Eine andere Lösung:

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

Das zweite würde scheitern mit:

    Expected: Any<String>
    Received: 123
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen