Ich möchte die Implementierung einer verspotteten Abhängigkeit pro Test ändern, indem ich das Verhalten des Standard-Mocks erweitere und es bei der Ausführung des nächsten Tests auf die ursprüngliche Implementierung zurücksetze.
Kurz gesagt, das versuche ich zu erreichen:
- Mock Abhängigkeit
- Scheinimplementierung in einem einzigen Test ändern / erweitern
- Wenn der nächste Test ausgeführt wird, kehren Sie zum ursprünglichen Modell zurück
Ich benutze gerade Jest v21
.
So würde ein typischer Scherztest aussehen:
__mocks__/myModule.js
const myMockedModule = jest.genMockFromModule('../myModule');
myMockedModule.a = jest.fn(() => true);
myMockedModule.b = jest.fn(() => true);
export default myMockedModule;
__tests__/myTest.js
import myMockedModule from '../myModule';
// Mock myModule
jest.mock('../myModule');
beforeEach(() => {
jest.clearAllMocks();
});
describe('MyTest', () => {
it('should test with default mock', () => {
myMockedModule.a(); // === true
myMockedModule.b(); // === true
});
it('should override myMockedModule.b mock result (and leave the other methods untouched)', () => {
// Extend change mock
myMockedModule.a(); // === true
myMockedModule.b(); // === 'overridden'
// Restore mock to original implementation with no side effects
});
it('should revert back to default myMockedModule mock', () => {
myMockedModule.a(); // === true
myMockedModule.b(); // === true
});
});
Folgendes habe ich bisher versucht:
1 - mockFn.mockImplementationOnce (fn)
Profis
- Kehrt nach dem ersten Aufruf zur ursprünglichen Implementierung zurück
Nachteile
- Es wird unterbrochen, wenn der Test
b
mehrmals aufgerufen wird - Die ursprüngliche Implementierung wird erst wiederhergestellt, wenn sie
b
nicht aufgerufen wird (Leck im nächsten Test).
Code:
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
myMockedModule.b.mockImplementationOnce(() => 'overridden');
myModule.a(); // === true
myModule.b(); // === 'overridden'
});
2 - jest.doMock (Modulname, Fabrik, Optionen)
Profis
- Verspottet bei jedem Test explizit neu
Nachteile
- Die Standard-Mock-Implementierung kann nicht für alle Tests definiert werden
- Das Erzwingen der Standardimplementierung kann nicht erweitert werden, um jede verspottete Methode erneut zu deklarieren
Code:
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
jest.doMock('../myModule', () => {
return {
a: jest.fn(() => true,
b: jest.fn(() => 'overridden',
}
});
myModule.a(); // === true
myModule.b(); // === 'overridden'
});
3 - Manuelles Verspotten mit Setter-Methoden (wie hier erklärt )
Profis
- Volle Kontrolle über verspottete Ergebnisse
Nachteile
- Viel Boilerplate-Code
- Langfristig schwer zu pflegen
Code:
__mocks__/myModule.js
const myMockedModule = jest.genMockFromModule('../myModule');
let a = true;
let b = true;
myMockedModule.a = jest.fn(() => a);
myMockedModule.b = jest.fn(() => b);
myMockedModule.__setA = (value) => { a = value };
myMockedModule.__setB = (value) => { b = value };
myMockedModule.__reset = () => {
a = true;
b = true;
};
export default myMockedModule;
__tests__/myTest.js
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
myModule.__setB('overridden');
myModule.a(); // === true
myModule.b(); // === 'overridden'
myModule.__reset();
});
4 - jest.spyOn (Objekt, Methodenname)
Nachteile
- Ich kann nicht
mockImplementation
zum ursprünglichen verspotteten Rückgabewert zurückkehren, was sich auf die nächsten Tests auswirkt
Code:
beforeEach(() => {
jest.clearAllMocks();
jest.restoreAllMocks();
});
// Mock myModule
jest.mock('../myModule');
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
const spy = jest.spyOn(myMockedModule, 'b').mockImplementation(() => 'overridden');
myMockedModule.a(); // === true
myMockedModule.b(); // === 'overridden'
// How to get back to original mocked value?
});
javascript
unit-testing
mocking
jestjs
Andrea Carraro
quelle
quelle
Antworten:
Ein schönes Muster zum Schreiben von Tests ist das Erstellen einer Setup-Factory-Funktion, die die Daten zurückgibt, die Sie zum Testen des aktuellen Moduls benötigen.
Im Folgenden finden Sie einen Beispielcode, der Ihrem zweiten Beispiel folgt, obwohl die Bereitstellung von Standard- und Überschreibungswerten auf wiederverwendbare Weise möglich ist.
const spyReturns = returnValue => jest.fn(() => returnValue); describe("scenario", () => { const setup = (mockOverrides) => { const mockedFunctions = { a: spyReturns(true), b: spyReturns(true), ...mockOverrides } return { mockedModule: jest.doMock('../myModule', () => mockedFunctions) } } it("should return true for module a", () => { const { mockedModule } = setup(); expect(mockedModule.a()).toEqual(true) }); it("should return override for module a", () => { const EXPECTED_VALUE = "override" const { mockedModule } = setup({ a: spyReturns(EXPECTED_VALUE)}); expect(mockedModule.a()).toEqual(EXPECTED_VALUE) }); });
quelle
Vanilla JS
Verwenden Sie mockFn.mockImplementation (fn) .
import { funcToMock } from './somewhere'; jest.mock('./somewhere'); beforeEach(() => { funcToMock.mockImplementation(() => { /* default implementation */ }); }); test('case that needs a different implementation of funcToMock', () => { funcToMock.mockImplementation(() => { /* implementation specific to this test */ }); // ... });
Typoskript
Um zu verhindern, dass die Nachricht mockImplementation keine Eigenschaft von funcToMock ist , müssen Sie den Typ angeben, z. B. indem Sie die oberste Zeile von oben in die folgende ändern:
import { (funcToMock as jest.Mock) } from './somewhere';
Eine Frage zu diesem Problem finden Sie hier: jest typescript property mock existiert für type nicht
quelle
Wenig spät zur Party, aber wenn jemand anderes Probleme damit hat.
Wir verwenden TypeScript, ES6 und babel für die reaktionsnative Entwicklung.
Normalerweise verspotten wir externe NPM-Module im Stammverzeichnis
__mocks__
.Ich wollte eine bestimmte Funktion eines Moduls in der Auth-Klasse von aws-amplify für einen bestimmten Test überschreiben.
import { Auth } from 'aws-amplify'; import GetJwtToken from './GetJwtToken'; ... it('When idToken should return "123"', async () => { const spy = jest.spyOn(Auth, 'currentSession').mockImplementation(() => ({ getIdToken: () => ({ getJwtToken: () => '123', }), })); const result = await GetJwtToken(); expect(result).toBe('123'); spy.mockRestore(); });
Inhalt: https://gist.github.com/thomashagstrom/e5bffe6c3e3acec592201b6892226af2
Tutorial: https://medium.com/p/b4ac52a005d#19c5
quelle