wake-up-neo.com

Wie kann ich einen ES6-Modulimport mit Jest nachahmen?

Ich fange an zu denken, dass dies nicht möglich ist, aber ich möchte trotzdem fragen.

Ich möchte testen, ob eines meiner ES6-Module auf bestimmte Weise ein anderes ES6-Modul aufruft. Mit Jasmine ist das ganz einfach -

Der App-Code:

// myModule.js
import dependency from './dependency';

export default (x) => {
  dependency.doSomething(x * 2);
}

Und der Testcode:

//myModule-test.js
import myModule from '../myModule';
import dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    spyOn(dependency, 'doSomething');

    myModule(2);

    expect(dependency.doSomething).toHaveBeenCalledWith(4);
  });
});

Was ist das Äquivalent zu Jest? Ich denke, das ist so einfach, aber ich habe mir die Haare ausgerissen, um es herauszufinden.

Am nächsten komme ich, indem ich die imports durch requires ersetze und sie innerhalb der Tests/Funktionen verschiebe. Weder von denen sind Dinge, die ich tun möchte.

// myModule.js
export default (x) => {
  const dependency = require('./dependency'); // yuck
  dependency.doSomething(x * 2);
}

//myModule-test.js
describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    jest.mock('../dependency');

    myModule(2);

    const dependency = require('../dependency'); // also yuck
    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

Für Bonuspunkte würde ich das Ganze gerne zum Laufen bringen, wenn die Funktion in dependency.js ein Standardexport ist. Ich weiß jedoch, dass das Ausspionieren von Standardexporten in Jasmine nicht funktioniert (oder zumindest könnte ich es nie zum Laufen bringen), und hoffe daher nicht, dass es auch in Jest möglich ist.

203
Cam Jackson

Ich habe es durch einen Hack mit import * geschafft, dieses Problem zu lösen. Es funktioniert sogar für Named- und Default-Exporte!

Für einen benannten Export:

// dependency.js
export const doSomething = (y) => console.log(y)

// myModule.js
import { doSomething } from './dependency';

export default (x) => {
  doSomething(x * 2);
}

// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    dependency.doSomething = jest.fn(); // Mutate the named export

    myModule(2);

    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

Oder für einen Standardexport:

// dependency.js
export default (y) => console.log(y)

// myModule.js
import dependency from './dependency'; // Note lack of curlies

export default (x) => {
  dependency(x * 2);
}

// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    dependency.default = jest.fn(); // Mutate the default export

    myModule(2);

    expect(dependency.default).toBeCalledWith(4); // Assert against the default
  });
});

Wie Mihai Damian im Folgenden zu Recht ausführte, mutiert dies das Modulobjekt von dependency und führt zu anderen Tests. Wenn Sie diesen Ansatz verwenden, sollten Sie den ursprünglichen Wert speichern und ihn nach jedem Test erneut einstellen. Verwenden Sie dazu einfach die Methode spyOn () anstelle von jest.fn(), da sie das einfache Wiederherstellen des ursprünglichen Werts unterstützt und somit das zuvor erwähnte "Leaking" vermeidet.

177
Cam Jackson

Sie müssen das Modul verspotten und den Spion selbst einstellen:

import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency', () => ({
  doSomething: jest.fn()
}))

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    myModule(2);
    expect(dependency.doSomething).toBeCalledWith(4);
  });
});
131

Hinzufügen von mehr zu Andreas Antwort. Ich hatte das gleiche Problem mit ES6-Code, wollte aber die Importe nicht mutieren. Das sah abgedreht aus. Also habe ich das gemacht

import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency');

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    myModule(2);
  });
});

Außerdem wurde dependency.js im Ordner "__ mocks __" parallel zu dependency.js hinzugefügt. Das hat bei mir funktioniert. Dies gab mir auch die Möglichkeit, geeignete Daten aus der Scheinimplementierung zurückzugeben. Stellen Sie sicher, dass Sie den richtigen Pfad zu dem Modul angeben, das Sie verspotten möchten.

38
mdsAyubi

So verspotten Sie einen Standardexport eines ES6-Abhängigkeitsmoduls mithilfe von jest:

import myModule from '../myModule';
import dependency from '../dependency';

jest.mock('../dependency');

// If necessary, you can place a mock implementation like this:
dependency.mockImplementation(() => 42);

describe('myModule', () => {
  it('calls the dependency once with double the input', () => {
    myModule(2);

    expect(dependency).toHaveBeenCalledTimes(1);
    expect(dependency).toHaveBeenCalledWith(4);
  });
});

Die anderen Optionen haben in meinem Fall nicht funktioniert.

37
falsarella

Die Frage ist bereits beantwortet, kann aber folgendermaßen gelöst werden:

dependency.js

module.exports.doSomething = (x) => x

myModule.js:

const { doSomething } = require('./dependency')
module.exports = (x) => doSomething(x * 2)

myModule.spec.js:

jest.mock('../dependency')
const { doSomething } = require('../dependency')
const myModule = require('../myModule')
describe('myModule', () => {
    it('calls the dependency with double the input', () => {
      doSomething.mockImplementation((x) => x * 10)

      myModule(2);

      expect(doSomething).toHaveBeenCalledWith(4);
      console.log(myModule(2)) // 40
    });
  });
0
Slim

Ich habe das anders gelöst. Angenommen, Sie haben Ihre dependency.js

export const myFunction = () => { }

Ich erstelle daneben eine depdency.mock.js-Datei mit folgendem Inhalt:

export const mockFunction = jest.fn();

jest.mock('dependency.js', () => ({ myFunction: mockFunction }));

und im Test, bevor ich die Datei importiere, die die von mir verwendete Abhängigkeit hat:

import { mockFunction } from 'dependency.mock'
import functionThatCallsDep from './tested-code'

it('my test', () => {
    mockFunction.returnValue(false);

    functionThatCallsDep();

    expect(mockFunction).toHaveBeenCalled();

})
0
Felipe Leusin