Jest: Wie man eine bestimmte Methode einer Klasse verspottet

Lesezeit: 3 Minuten

Benutzer-Avatar
CrazySynthax

Nehmen wir an, ich habe die folgende Klasse:

export default class Person {
    constructor(first, last) {
        this.first = first;
        this.last = last;
    }
    sayMyName() {
        console.log(this.first + " " + this.last);
    }
    bla() {
        return "bla";
    }
}

Angenommen, ich möchte eine verspottete Klasse erstellen, in der die Methode „sayMyName“ verspottet wird und die Methode „bla“ unverändert bleibt.

Der Test, den ich geschrieben habe, lautet:

const Person = require("../Person");

jest.mock('../Person', () => {
    return jest.fn().mockImplementation(() => {
        return {sayMyName: () => {
            return 'Hello'
        }};
    });
});


let person = new Person();
test('MyTest', () => {
    expect(person.sayMyName()).toBe("Hello");
    expect(person.bla()).toBe("bla");
})

Die erste „expect“-Anweisung wird bestanden, was bedeutet, dass „sayMyName“ erfolgreich verspottet wurde. Aber das zweite ‘expect’ schlägt mit dem Fehler fehl:

TypeError: person.bla ist keine Funktion

Ich verstehe, dass die verspottete Klasse alle Methoden gelöscht hat. Ich möchte wissen, wie man eine Klasse so verspottet, dass nur bestimmte Methoden verspottet werden.

Benutzer-Avatar
Ninh Pham

Beantworten Sie die Frage nicht wirklich, aber ich möchte einen Anwendungsfall zeigen, in dem Sie eine abhängige Klasse verspotten möchten, um eine andere Klasse zu überprüfen.

Zum Beispiel: Foo kommt drauf an Bar. Im Inneren Foo erstellte eine Instanz von Bar. Du willst spotten Bar zum Prüfen Foo.

Bar-Klasse

class Bar {
  public runBar(): string {
    return 'Real bar';
  }
}

export default Bar;

Foo Klasse

import Bar from './Bar';

class Foo {
  private bar: Bar;

  constructor() {
    this.bar = new Bar();
  }

  public runFoo(): string {
    return 'real foo : ' + this.bar.runBar();
  }
}

export default Foo;


Die Prüfung:

import Foo from './Foo';
import Bar from './Bar';

jest.mock('./Bar');

describe('Foo', () => {
  it('should return correct foo', () => {
    // As Bar is already mocked,
    // we just need to cast it to jest.Mock (for TypeScript) and mock whatever you want
    (Bar.prototype.runBar as jest.Mock).mockReturnValue('Mocked bar');
    const foo = new Foo();
    expect(foo.runFoo()).toBe('real foo : Mocked bar');
  });
});


Hinweis: Dies funktioniert nicht, wenn Sie Pfeilfunktionen verwenden, um Methoden in Ihrer Klasse zu definieren (da sie Unterschiede zwischen Instanzen sind). Wenn Sie es in eine reguläre Instanzmethode konvertieren, würde es funktionieren.

Siehe auch jest.requireActual (Modulname)

  • Ich kenne die Antwort darauf nicht, also bin ich wirklich neugierig: Würde dies Person.prototype.sayMyName für alle anderen Tests ändern, die nach diesem laufen?

    – Martin

    8. Oktober 2018 um 18:52 Uhr

  • @ Martin Ja, das tut es.

    – Frondor

    15. Oktober 2018 um 18:44 Uhr

  • Ich denke nicht, dass dies eine gute Praxis ist. Es verwendet weder Jest noch ein anderes Framework, um die Methode zu simulieren, und Sie müssen sich extra anstrengen, um die Methode wiederherzustellen.

    – Bruno Brant

    4. September 2019 um 15:16 Uhr

  • Unter stackoverflow.com/a/56565849/1248209 finden Sie Antworten dazu, wie Sie dies in Jest mit spyOn richtig machen.

    – Lockyy

    21. Oktober 2019 um 14:06 Uhr

Benutzer-Avatar
Madhamster

Habe eine ähnliche Frage gestellt und denke, eine Lösung gefunden zu haben. Dies sollte unabhängig davon funktionieren, wo die Person-Klasseninstanz tatsächlich verwendet wird.

const Person = require("../Person");

jest.mock("../Person", function () {
    const { default: mockRealPerson } = jest.requireActual('../Person');

    mockRealPerson.prototype.sayMyName = function () {
        return "Hello";
    }    

    return mockRealPerson
});

test('MyTest', () => {
    const person = new Person();
    expect(person.sayMyName()).toBe("Hello");
    expect(person.bla()).toBe("bla");
});

Benutzer-Avatar
Billy Reilly

Anstatt die Klasse zu verspotten, könnten Sie sie wie folgt erweitern:

class MockedPerson extends Person {
  sayMyName () {
    return 'Hello'
  }
}
// and then
let person = new MockedPerson();

Benutzer-Avatar
Saif Assad

Wenn Sie Typescript verwenden, können Sie Folgendes tun:

Person.prototype.sayMyName = jest.fn().mockImplementationOnce(async () => 
        await 'my name is dev'
);

Und in Ihrem Test können Sie so etwas tun:

const person = new Person();
const res = await person.sayMyName();
expect(res).toEqual('my name is dev');

Hoffe das hilft jemandem!

  • Wie können wir behaupten, dass der Schein gerufen wurde?

    – Jaspis-Blues

    2. Februar 2019 um 4:30 Uhr

1010030cookie-checkJest: Wie man eine bestimmte Methode einer Klasse verspottet

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy