ç°¡åã§ãããããããšæãããšã§èŠåŽããŠããŸãããã©ããããããç解ã§ããŸããã
ã¢ãžã¥ãŒã«ããããŸãã è€æ°ã®é¢æ°ããšã¯ã¹ããŒãããŸãã ãããmyModule.js
ã§ãïŒ
export function foo() {...}
export function bar() {...}
export function baz() {...}
ãã¹ãã®ããã«ã¢ãžã¥ãŒã«ã®ã¢ãã¯ã解é€ããŸãã
jest.unmock('./myModule.js');
ãã ããããã¯ãšã³ãã«ajaxåŒã³åºããè¡ãããã foo
ãã¢ãã¯ããå¿
èŠããããŸãã ãã®ãã¡ã€ã«å
ã®ãã¹ãŠã®é¢æ°ãã¢ãã¯ããªããŸãŸã«ããŠããããã®ã§ãããã¢ãã¯ãããfoo
ãæåŸ
ããŸãã ãŸããé¢æ°bar
ãšbaz
ã¯å
éšã§foo
åŒã³åºãããããã¹ãã§bar()
bar
ãåŒã³åºããšãã¢ãã¯ãããŠããªãfoo
ã
unmock
ãšmock
åŒã³åºããã¢ãžã¥ãŒã«å
šäœã§åäœããããšã¯ãjestã®ããã¥ã¡ã³ãã«èšèŒãããŠããŸãã ç¹å®ã®æ©èœãã¢ãã¯ããã«ã¯ã©ãããã°ããã§ããïŒ ã³ãŒããä»»æã«å¥ã
ã®ã¢ãžã¥ãŒã«ã«åå²ããŠãé©åã«ãã¹ãã§ããããã«ããã®ã¯ã°ãããŠããŸãã
詳现ã«åæãããšãjest-mockã¯ã¢ãžã¥ãŒã«å šäœã®ASTãçæãããã®ASTã䜿çšããŠãå ã®ãšã¯ã¹ããŒãã«æºæ ããã¢ãã¯ã¢ãžã¥ãŒã«ãäœæããŠããããã§ãïŒ https ïŒ
Pythonã®ã¢ãã¯ïŒhttps://docs.python.org/3/library/unittest.mock-examples.htmlïŒãªã©ã®ä»ã®ãã¹ããã¬ãŒã ã¯ãŒã¯ã䜿çšãããšãç¹å®ã®é¢æ°ãã¢ãã¯ã§ããŸãã ããã¯åºæ¬çãªãã¹ãã®æŠå¿µã§ãã
ã¢ãžã¥ãŒã«ã®äžéšãã¢ãã¯ããæ©èœã匷ããå§ãããŸãã jest-mockã¯ãã¢ãã¯ããã®ãšã¯ã¹ããŒããæ¡ä»¶ä»ãã§ç¡èŠããå ã®å®è£ ãåç §ããããã«å€æŽããå¿ èŠããããšæããŸãã
ã§ãããïŒ
jest.unmock('./myModule.js');
const myModule = require('myModule');
myModule.foo = jest.fn();
http://facebook.github.io/jest/docs/api.html#mock-functionsãåç §ããŠ
require
ãã©ã®ããã«æ©èœãããã«ã€ããŠæ ¹æ¬çãªèª€è§£ããããšæããŸãã require()
ãåŒã³åºããšãã¢ãžã¥ãŒã«ã®ã€ã³ã¹ã¿ã³ã¹ãååŸã§ããŸããã ã¢ãžã¥ãŒã«ã®é¢æ°ãžã®åç
§ãæã€ãªããžã§ã¯ããååŸããŸãã å¿
èŠãªã¢ãžã¥ãŒã«ã®å€ãäžæžããããšãç¬èªã®åç
§ãäžæžããããŸãããå®è£
ã¯å
ã®åç
§ãä¿æããŸãã
ããªãã®äŸã§ã¯ã myModule.foo()
ãåŒã³åºããšãã¯ããã¢ãã¯ããŒãžã§ã³ãåŒã³åºããŸãã ãã ããå
éšã§foo()
ãåŒã³åºãmyModule.bar()
ãåŒã³åºãå Žåããããfoo()
ããfoo
ã¯_äžæžããããããŒãžã§ã³ã§ã¯ãããŸãã_ã ããªããç§ãä¿¡ããŠããªããªããããªãã¯ãããè©Šãããšãã§ããŸãã
ãããã£ãŠãããªãã説æããäŸã¯ãç§ãæ±ããŠããåé¡ã«ã¯äžååã§ãã ç§ãç¥ããªãããšãç¥ã£ãŠããŸããïŒ
@cpojer
ç§ã¯ãããããç解ããŠãããšä¿¡ããŠããŸãã ããããbabelãã¢ãžã¥ãŒã«ãã³ã³ãã€ã«ããæ¹æ³ã¯ããããç解ãããããããã®ã§ã¯ãªããç§ã¯ããªãã®æ··ä¹±ãç解ããŠããŸãã ã¢ãžã¥ãŒã«ãåããå®éã®ES2015ç°å¢ã§ãããã©ã®ããã«åäœãããã¯æ£ç¢ºã«ã¯ããããŸãããäž»ãªçç±ã¯ããã®ãããªç°å¢ãçŸåšååšããªãããã§ãïŒChrome Canaryã®ææ°ããŒãžã§ã³ãé€ããŠããŸã è©ŠããŠããŸããïŒã äœãèµ·ãããã説æããããã«ãç§ãã¡ã¯ããªãã®babelã³ãŒãã®ã³ã³ãã€ã«ãããåºåãèŠãå¿ èŠããããŸãã 次ã®ããã«ãªããŸãã
var foo = function foo() {};
var bar = function bar() { foo(); };
exports.foo = foo;
exports.bar = bar;
ãã®å Žåãfooãã¢ãã¯ã§ããªãããšã¯ç¢ºãã«æ£ããã§ããæåã®åé¡ãæ£ããèªãã§ããªãããšããè©«ã³ããŸããã foo
ãã©ã®ããã«åŒã³åºããããã«ã€ããŠexports.foo()
ãšæ³å®ããŸããã
ãã ããã³ãŒãã次ã®ããã«å€æŽããå ŽåïŒ
var foo = function foo() {};
var bar = function bar() { exports.foo(); };
exports.foo = foo;
exports.bar = bar;
次ã«ããã¹ããã¡ã€ã«ã§æ¬¡ã®ããšãè¡ããŸãã
var module = require('../module');
module.foo = jest.fn();
module.bar();
æåŸ ã©ããã«åäœããŸãã ããã¯ãES2015ã䜿çšããªãFacebookã§è¡ã£ãŠããããšã§ãã
ES2015ã¢ãžã¥ãŒã«ã«ã¯ããšã¯ã¹ããŒããããã®ã«å¯ŸããŠäžå€ã®ãã€ã³ãã£ã³ã°ãããå ŽåããããŸãããbabelãçŸåšã³ã³ãã€ã«ããåºã«ãªãã³ã³ãã€ã«æžã¿ã³ãŒãã¯ããã®ãããªå¶çŽã匷å¶ããŸããã çŸåšããã€ãã£ãã«ãµããŒããããŠããã¢ãžã¥ãŒã«ã䜿çšããå³å¯ãªES2015ã¢ãžã¥ãŒã«ç°å¢ã§ããªããæ±ããŠãããã®ãæ£ç¢ºã«ãµããŒãããæ¹æ³ã¯ãããŸããã jest-mock
æ©èœããæ¹æ³ã¯ãã¢ãžã¥ãŒã«ã³ãŒããåé¢ããŠå®è¡ããã¢ãžã¥ãŒã«ã®ã¡ã¿ããŒã¿ãååŸããŠã¢ãã¯é¢æ°ãäœæããããšã§ãã ç¹°ãè¿ããŸããããã®å Žåã foo
ã®ããŒã«ã«ãã€ã³ãã£ã³ã°ãå€æŽããæ¹æ³ã¯ãããŸããã ãããå¹æçã«å®è£
ããæ¹æ³ã«ã€ããŠã¢ã€ãã¢ãããå Žåã¯ããããŸãã¯ãã«ãªã¯ãšã¹ãã§è²¢ç®ããŠãã ããã ãã®ãããžã§ã¯ãã®è¡åèŠç¯ããããããã§èªãããšãã§ããŸãïŒ https ïŒ
ãã®äŸã®æ£ãã解決çã¯ãfooãã¢ãã¯ããã®ã§ã¯ãªããfooãåŒã³åºããŠããé«ã¬ãã«ã®APIïŒXMLHttpRequestã代ããã«äœ¿çšããæœè±¡åãªã©ïŒãã¢ãã¯ããããšã§ãã
@cpojer詳ãã説æããããšãããããŸãã ç§ã®èšèªã§ããªããæããããç³ãèš³ãããŸãããç§ã¯ç§ã®ãšã³ãžãã¢ãªã³ã°ã®å·çã§éåžžã«å¹ççã§ãããããŠç§ã¯ã§ããã ãæ©ãç§ã®äž»åŒµãäŒãããã§ãã å
šäœåãææ¡ããããã«ãç§ã¯ãã®åé¡ãç解ããããã«5æéè²»ããã2ã€ã®è©³çŽ°ãªã³ã¡ã³ããæžããŸããããã®åŸãäž¡æ¹ã®ã¹ããŒãã¡ã³ãã®èŠç¹ãå®å
šã«èŠéããçãã¡ãã»ãŒãžã§éããŸããã ãã®ããã次ã®ã¡ãã»ãŒãžã§ã¯ããæ ¹æ¬çãªèª€è§£ãããããšè¿°ã¹ãŸãããããã¯ã1ïŒç§ãèšã£ãŠããããšãç解ããŠããªãã£ããã2ïŒ require()
ç解ããŠããªãã£ãããã§ããããã¯ããããããããšã«ãªãã·ã§ã³1ã§ããã
ç§ã¯èªåã®åé¡ã®å¯èœãªè§£æ±ºçãèãããããåé¿ããããã«ãä»ã®ãšããäœã¬ãã«ã®APIãã¢ãã¯ããŸããããé¢æ°ãçŽæ¥ã¢ãã¯ããæ¹æ³ãããã¯ãã§ããããã¯éåžžã«äŸ¿å©ã§ãã
ç§ã¯ãããã§ãããšäŸ¿å©ã ãšåæããŸãããJSã«ã¯ïŒããããé ãïŒéçåæãåãã£ãŠè¡ããã«ãããè¡ãè¯ãæ¹æ³ã¯ãããŸãã:(
@cpojer ïŒ5ãæåŸã«ããã«é£ã³èŸŒãããšãéã§ãããã©ããã¯ããããŸããããããã«é¢ããä»ã®äŒè©±ã¯èŠã€ãããŸããã§ããã
äžèšã®ææ¡ããé£ã³éããŠãåãã¢ãžã¥ãŒã«å ã®ããé¢æ°ãå¥ã®é¢æ°ããã¢ãã¯ã¢ãŠãããããã«ãããè¡ããŸããã
jest.unmock('./someModule.js');
import someModule from './someModule.js';
it('function1 calls function 2', () => {
someModule.function2 = jest.fn();
someModule.function1(...);
expect(someModule.function2).toHaveBeenCalledWith(...);
});
ããã¯1ã€ã®ãã¹ãã§æ©èœããŸããã1ã€ã®it(...);
ãããã¯ã ãã«åé¢ãããæ¹æ³ã§ãããéæããæ¹æ³ãèŠã€ããããŸããfunction2
ããã¹ãããããšãå°é£ã«ããŸãã ä»»æã®ãã³ãïŒ
ããªãã¯åŒã³åºãããšãã§ããŸã.mockClear
ã«æ©èœäžã®beforeEach
ãŸãã¯ãé»è©±jest.clearAllMocks()
ããªãã¯åè«16ã䜿çšããŠããå Žåã
ãã@cpojerïŒ Jest 16ã䜿çšããŠããŸãã jest.clearAllMocks()
ãsomeModule.function2.mockClear()
æ©èœããŸããã ãããã¯ãã¢ãã¯ãã¢ãžã¥ãŒã«å
šäœã§ãããã€ã³ããŒããããã¢ãžã¥ãŒã«ã®æ©èœã§ã¯ãªãå Žåã«ã®ã¿æ©èœããŸãã ç§ã®ãããžã§ã¯ãã§ã¯ãé¢æ°ã¯åŸç¶ã®ãã¹ãã§ã¢ãã¯ããããŸãŸã§ãã ãããäºæãããŠããªãå Žåã¯ãå°ããªãµã³ãã«ãããžã§ã¯ãã§è€è£œããŠãæ°ããåé¡ãäœæã§ãããã©ããã確èªããŸãã è¯ãã¢ã€ãã¢ïŒ
@ cpojer-
ãã®äŸã®æ£ãã解決çã¯ãfooãã¢ãã¯ããã®ã§ã¯ãªããfooãåŒã³åºããŠããé«ã¬ãã«ã®APIïŒXMLHttpRequestã代ããã«äœ¿çšããæœè±¡åãªã©ïŒãã¢ãã¯ããããšã§ãã
ç§ã¯JestãåããŠäœ¿çšããåæ§ã®åé¡ã«èŠããã§ããŸãã ç§ã䜿çšããŠããŸãaxiosããã³ãããã®äžã«äœ¿çšããã XMLHttpRequest
ãç§ã¯ã¢ãã¯ããããªãaxios
ãå®éã®æš¡æ¬ããããã«XMLHttpRequest
ã ç§ããèªåã§äœããã®ã¡ãœãããå®è£
ããªããã°ãªããªããšæããããããã ããã¯æ£ããã¢ãããŒãã§ããïŒ
ããããšãïŒ
ããããã®ãããªãã®ã¯ããªããæ£ããéã«å°ãã¯ãã§ãïŒ :) jest.fn
ãããè¯ãAPIãšããŠäœ¿çšããŸãããïŒD
ããã§ã®ã³ã¡ã³ãã«é¢ãã@cpojer ïŒ https ïŒ
ES2015ã§ãããã©ã®ããã«è¡ããŸããïŒ
// myModyle.js
export foo = (string) => "foo-" + string
export bar = (string2) => foo(string2)
// myModule.test.js
var module = require('./myModule');
// how do I mock foo here so this test passes?
expect(bar("hello")).toEqual("test-hello")
解決çãæ¢ããŠããããã«åºãããã人ã«ãšã£ãŠã1ã€ã®ãã¡ã€ã«ã«å€ãã®const /é¢æ°ããšã¯ã¹ããŒãããç§ããã¹ãããŠãããã¡ã€ã«ã«ããããã€ã³ããŒããããšãã以äžã¯ç§ã®ããã«åããŠããããã§ã
`` javascript
function mockFunctions() {
const original = require.requireActual('../myModule');
return {
...original, //Pass down all the exported objects
test: jest.fn(() => {console.log('I didnt call the original')}),
someFnIWantToCurry: {console.log('I will curry the original') return jest.fn((...args) => original.someFnIWantToCurry(...args)}),
}
jest.mock('../myModule', () => mockFunctions());
const storage = require.requireMock('../myModule');
@ainesophaur ãããã§äœãééã£ãŠããã®ãããããªãã ããããããã¯æ©èœããªãããã§ã
ç§ã¯çŸåšjest18.1ïŒããã³create-react-app 0.9.4ïŒã䜿çšããŠããŸã
...<codes from comment above>..
// Let's say the original myModule has a function doSmth() that calls test()
storage.doSmth();
expect(storage.test).toHaveBeenCalled();
ãã®åŸããã¹ãã¯æ¬¡ã®ããã«å€±æããŸãã
expect(jest.fn()).toHaveBeenCalled()
Expected mock function to have been called.
@huyph jestãåŒã³åºããããã©ããããã¹ãããã«ã¯ãdoSmthã¡ãœãããštestã¡ãœãããã¢ãã¯ããå¿ èŠããããŸãã ã¢ãã¯ã³ãŒãã®ã¹ãããããæäŸã§ããã°ãäœãåé¡ãªã®ãã確èªã§ããŸã
@ainesophaur ...test()
ã¡ãœãããã¢ãã¯ããããã®ãã®ã ãšæããŸãããïŒ ãã®éšåïŒ test: jest.fn(() => {console.log('I didnt call the original')}),
@ainesophaurç§ãããªãã®ã³ãŒããè©ŠããŸããã ããããããã¯ç§ã«ãšã£ãŠã¯ããŸããããŸããã§ããã ã¢ãã¯é¢æ°ãå®è¡ããããšã¯ãããŸããã ãããã£ãŠãæåŸ ã¯æ±ºããŠæºããããŸããã
ããã¯ãäžèšã®ãããªäœæ¥ãå¿ èŠãªæ¹æ³ã«åºæã®ãã®ã ãšæããŸã...ããã«å¯Ÿãã解決çãããã°ããã®ã«ãšæããŸãã
@cpojeréšåçã«ã¢ãã¯ããã¢ãžã¥ãŒã«ã«é¢ããŠäœãæ°ããããšã¯ãããŸããïŒ
@ rantonmattei ïŒ @ huyphã¢ãã¯å®çŸ©ã®ã¹ãããããšå®è¡äžã®ãã¹ãã確èªããå¿ èŠããããŸãã å®éã®å®è£ ãã¡ã€ã«ãå¿ èŠ/ã€ã³ããŒããããåã«ãã¢ãã¯ãå®çŸ©ããå¿ èŠããããŸãã JESTã䜿çšããŠãããã°ããçµã¡ãŸããããnode_modulesã©ã€ãã©ãªã§ããããšã¢ããªå ã®ãã¡ã€ã«ã§ããããšãæçµçã«å¿ èŠãªãã®ãã¹ãŠãã¢ãã¯ããããã«ãªã£ãã®ãèŠããŠããŸãã ATMã®æéã¯å°ã足ããŸããããJestã䜿çšããŠåãçµãã ãããžã§ã¯ãã®ãã¹ããããã€ã玹ä»ããŸãã
äŸåé¢ä¿ãããã¡ã€ã«ãã¢ãã¯ãã
ãã®äŸã®å®éã®é¢æ°å®çŸ©ã¯ãreact-nativeã«ãã£ãŠè¡ãããŸãããã¡ã€ã«ãreact-native / Libraries / Utilities /dismissKeyboard.jsããã¢ãã¯ããŠããŸãã
ããã¯__mocks__/react-native/Libraries/Utilities/dismissKeyboard.js
äžã®ã¢ãã¯ãã¡ã€ã«ã§ã
function storeMockFunctions() {
return jest.fn().mockImplementation(() => true);
}
jest.mock('react-native/Libraries/Utilities/dismissKeyboard', () => storeMockFunctions(), { virtual: true });
const dismissKeyboard = require('react-native/Libraries/Utilities/dismissKeyboard');
exports = module.exports = storeMockFunctions;
äžèšã§äœ¿çšãããã¹ããã¡ã€ã«ãèŠã€ãããŸããããã¢ãžã¥ãŒã«ãå¿ èŠãªãããªãã®ã§ãããjestã¯ããã__mocks__ã§èŠã€ããŠã次ã®ãããªããšãè¡ãããšãã§ããŸããã
expect(dismissKeyboard.mock.calls).toHaveLength(1);
å¶åŸ¡ãããã¡ã€ã«ãã¢ãã¯ãã
å®éã®é¢æ°å®çŸ©
export const setMerchantStores = (stores) => storage.set('stores', stores);
ã¢ãã¯ä»ãã®ãã¹ããã¡ã€ã«
const { storeListEpic, offerListEpic } = require('../merchant');
function storeMockFunctions() {
const original = require.requireActual('../../common/Storage');
return {
...original,
setMerchantStores: jest.fn((...args) => original.setMerchantStores(...args)),
setMerchantOffers: jest.fn((...args) => original.setMerchantOffers(...args)),
};
}
jest.mock('../../common/Storage', () => storeMockFunctions());
import * as storage from '../../common/Storage';
afterEach(() => {
storage.setMerchantStores.mockClear();
});
it('handle storeListEpic type STORE_LIST_REQUEST -> STORE_LIST_SUCCESS', async () => {
const scope = nock('http://url')
.get('/api/merchant/me/stores')
.reply(200, storeData);
const result = await storeListEpic(ActionsObservable.of(listStores())).toPromise();
expect(storage.setMerchantStores.mock.calls).toHaveLength(1);
expect(await storage.getMerchantStores()).toEqual({ ids: storesApiData.result, list: storesApiData.entities.store});
});
@ainesophaurãå ±æããŠããã ãããããšãããããŸãã ç§ã¯ãŸã ãããjest18.1ã§åäœãããããšãã§ããŸããã ãããç§ã®ã³ãŒãã§ãïŒ
it('should save session correctly', () => {
function mockFunctions() {
const original = require.requireActual('./session');
return {
...original,
restartCheckExpiryDateTimeout: jest.fn((() => {
console.log('I didn\'t call the original');
})),
}
}
jest.mock('./session', () => mockFunctions());
const mockSession = require('./session');
// NOTE: saveSession() will call the original restartCheckExpiryDateTimeout() instead of my
// mock one. However, mockSession.restartCheckExpiryDateTimeout() does call the mock one
mockSession.saveSession('', getTomorrowDate(), 'AUTH');
// mockSession.restartCheckExpiryDateTimeout(); // does print out "I didn't call the original"
expect(mockSession.restartCheckExpiryDateTimeout).toHaveBeenCalled();
});
session.js
export function saveSession(sessionId, sessionExpiryDate, authToken) {
....
restartCheckExpiryDateTimeout(sessionExpiryDate);
...
}
....
export function restartCheckExpiryDateTimeout(...) {
....
}
ãã®åé¡ã解決ããæ¹æ³ãèŠã€ãããŸããã ãããåéã§ããŸããïŒ @cpojer
@huyphãšã¯ã¹ããŒãsaveSession
ã¯ãã¢ãžã¥ãŒã«ãçµç±ããŠmodule.restartCheckExpiryDateTimeout
ãåŒã³åºã代ããã«ãããŒã«ã«ã§å®çŸ©ãããrestartCheckExpiryDateTimeout
ãåŒã³åºããŸããã€ãŸããã¢ãã¯ãããmodule.restartCheckExpiryDateTimeout
saveSession
ã saveSession
ãå®éã«å®çŸ©ãããrestartCheckExpiryDateTimeout
é¢æ°ãåŒã³åºããŠããããã saveSession
ã«ãã£ãŠæ€åºãããŸããã
saveSession
ãconstã«å²ãåœãŠãŠããã saveSession.restartCheckExpiryDateTimeout = () => {...logic}
ãŸãã ã次ã«ã saveSession.saveSession
å
ããã restartCheckExpiryDateTimeout
ã ãã§ãªãã saveSession.restartCheckExpiryDateTimeout
åŒã³åºããŸãã ã¡ãœãããå®çŸ©ããå®éã®é¢æ°saveSession
代ããã«ãæ°ããconstããšã¯ã¹ããŒãããŸãã 次ã«ã someVar.saveSession()
åŒã³åºããšãå
éšçã«saveSession.restartCheckExpiryDateTimeout()
ãåŒã³åºãããŸãããããã¯çŸåšã¢ãã¯ãããŠããŸãã
restartCheckExpiryDateTimeout()
ã¯ãšã¯ã¹ããŒããããé¢æ°ã§ããããšãè¿œå ããå¿
èŠããããŸãã saveSession()
å
ã§ããŒã«ã«ã«å®çŸ©ãããé¢æ°ã§ã¯ãããŸãã...ïŒäžèšã®ç§ã®ã³ã¡ã³ããæŽæ°ããŸããïŒã ãã®å Žåã module.saveSession()
ã¯ãã¢ãã¯ãããæ£ããmodule.restartCheckExpiryDateTimeout()
ãåŒã³åºãå¿
èŠããããšæããŸãã
ããããç§ã¯ããªããææ¡ããããšãäžã«ç€ºããŸãã saveSession()
ãšrestartCheckExpiryDateTimeout()
äž¡æ¹ãå¥ã®å®æ°ã«ç§»åããŸãã ããããšã
saveSessionã®ã¹ã³ãŒãã§å®çŸ©ãããŠããªãããšãç解ããŠããŸãã saveSessionã¯
芪ã¹ã³ãŒãã§å
åŒã¡ãœãããåŒã³åºããŸãã ç§ã¯ããã«äœåºŠãééããŸãã
ãããŠç§ãææ¡ããããšã¯ããã®ããã«åãã
2017幎5æ8æ¥ååŸ8æ38åããHuyPhamã [email protected]ã¯æ¬¡ã®ããã«æžããŠããŸãã
restartCheckExpiryDateTimeoutïŒïŒããšã¯ã¹ããŒããããããšãè¿œå ããå¿ èŠããããŸã
é¢æ°ã saveSessionïŒïŒå ã§ããŒã«ã«ã«å®çŸ©ãããé¢æ°ã§ã¯ãããŸãããããããç§ã¯ããªããææ¡ããããšãäžã«ãããŸãã ããããšã
â
ããªããèšåãããã®ã§ããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/facebook/jest/issues/936#issuecomment-300029003 ããŸãã¯ãã¥ãŒã
ã¹ã¬ãã
https://github.com/notifications/unsubscribe-auth/AEeBdsmpOOmzvcUHB3D_-Z7MChIzt10Pks5r37WYgaJpZM4IPGAH
ã
è©ŠããŠã¿ãŸãã..ç§ã¯ãããèŠã€ããŸããïŒ
ããã¯æ©èœããŸãã:(ã€ãŸããå ã®restartCheckExpiryDateTimeoutïŒïŒã¯åŒãç¶ãåŒã³åºãããŸãïŒ
export session = {
saveSession: () => {
session.restartCheckExpiryDateTimeout();
},
restartCheckExpiryDateTimeout: () => {},
}
ããã¯æ©èœããŸãïŒã€ãŸãã代ããã«ã¢ãã¯ã®restartCheckExpiryDateTimeoutïŒïŒãåŒã³åºãããŸãïŒã éãã¯ãç¢å°åœ¢åŒã®ä»£ããã«function()
ã䜿çšããããšãšã this.
代ããã«session.
export session = {
saveSession: function() {
this.restartCheckExpiryDateTimeout();
},
restartCheckExpiryDateTimeout: () => {},
}
ãããã®ã³ãŒãããã©ã³ã¹ãã€ã«ããåè«ã§åé¡ã«ãªãå¯èœæ§ããããŸã...ã
ããããpojoã§ã¯ãªãã¯ã©ã¹ãªããžã§ã¯ããšããŠãšã¯ã¹ããŒãããŠã¿ãŠãã ããã ç§ã¯ä¿¡ããŠããŸã
ãã©ã³ã¹ãã€ã©ãŒã¯å€æ°ãç°ãªãæ¹æ³ã§å·»ãäžããŸãã ç§ãã¡ã¯åãããã«ãªããŸã
ãã¹ããçŽæããŸããç§ããããžã§ã¯ãã«åå ããŠããçŽå幎ãçµã¡ãŸããã
ããã¯åè«ã䜿ã£ãŠããŸããããç§ã¯ãã®åé¡ãããèŠããŠããŸãããããŠç§ã¯æçµçã«èŠããŠããŸã
解決çãèŠã€ããã
2017幎5æ9æ¥åå0æ53åããHuyPhamã [email protected]ã¯æ¬¡ã®ããã«æžããŠããŸãã
è©ŠããŠã¿ãŸãã..ç§ã¯ãããèŠã€ããŸããïŒ
ããã¯æ©èœããŸãã:(ã€ãŸããå ã®restartCheckExpiryDateTimeoutïŒïŒã¯
ãŸã åŒã°ããïŒãšã¯ã¹ããŒãã»ãã·ã§ã³= {
saveSessionïŒïŒïŒ=> {
session.restartCheckExpiryDateTimeoutïŒïŒ;
}ã
restartCheckExpiryDateTimeoutïŒïŒïŒ=> {}ã
}ããã¯æ©èœããŸãã:(ã€ãŸããå ã®restartCheckExpiryDateTimeoutïŒïŒã¯
ãŸã åŒã°ããïŒãšã¯ã¹ããŒãã»ãã·ã§ã³= {
saveSessionïŒfunctionïŒïŒ{
this.restartCheckExpiryDateTimeoutïŒïŒ;
}ã
restartCheckExpiryDateTimeoutïŒïŒïŒ=> {}ã
}ãããã®ã³ãŒãããã©ã³ã¹ãã€ã«ããåè«ã§åé¡ã«ãªãå¯èœæ§ããããŸã...ã
â
ããªããèšåãããã®ã§ããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/facebook/jest/issues/936#issuecomment-300060975 ããŸãã¯ãã¥ãŒã
ã¹ã¬ãã
https://github.com/notifications/unsubscribe-auth/AEeBdrRQExycPYiGtvm7qYi5G87w6b6Oks5r3_FlgaJpZM4IPGAH
ã
@sorahnåãåé¡ã es6
+ babel
ãã¢ãã¯ããæ¹æ³ã¯ïŒ
@cpojerã€ãŸãã es6
+ babel
ã export const function xx() {}
ãå€ãã®é¢æ°ããšã¯ã¹ããŒãããŸãã Jest
ã¯ãåŒã³åºãããã¢ãžã¥ãŒã«ïŒãã¡ã€ã«ïŒå
ã®é¢æ°ãã¢ãã¯ããæ¹æ³ããããŸãããåãã¢ãžã¥ãŒã«ïŒãã¡ã€ã«ïŒå
ã®ä»ã®é¢æ°ã«ãã£ãŠïŒ ç§ã¯ããããã¹ãããŸããããã¯ç§ãæ£ããããã§ãã commonjs
ãã¿ãŒã³ã®å Žåã®ã¿ãJestã¯äŸã®ããã«é¢æ°ãæ£åžžã«ã¢ãã¯ã§ããŸãã
@ainesophaurãæ©èœããŠããŸããã
ã¢ãžã¥ãŒã«ïŒ
export const getMessage = (num: number): string => {
return `Her name is ${genName(num)}`;
};
export function genName(num: number): string {
return 'novaline';
}
ãã¹ãïŒ
function mockFunctions() {
const original = require.requireActual('../moduleA');
return {
...original,
genName: jest.fn(() => 'emilie')
}
}
jest.mock('../moduleA', () => mockFunctions());
const moduleA = require('../moduleA');
describe('mock function', () => {
it('t-0', () => {
expect(jest.isMockFunction(moduleA.genName)).toBeTruthy();
})
it('t-1', () => {
expect(moduleA.genName(1)).toBe('emilie');
expect(moduleA.genName).toHaveBeenCalled();
expect(moduleA.genName.mock.calls.length).toBe(1);
expect(moduleA.getMessage(1)).toBe('Her name is emilie');
expect(moduleA.genName.mock.calls.length).toBe(2);
});
});
ãã¹ãçµæïŒ
FAIL jest-examples/__test__/mock-function-0.spec.ts
â mock function ⺠t-1
expect(received).toBe(expected)
Expected value to be (using ===):
"Her name is emilie"
Received:
"Her name is novaline"
at Object.it (jest-examples/__test__/mock-function-0.spec.ts:22:35)
at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
mock function
â t-0 (1ms)
â t-1 (22ms)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 passed, 2 total
Snapshots: 0 total
Time: 0.215s, estimated 1s
äžèšã®ç§ã®æåŸã®ããã€ãã®ã³ã¡ã³ããèŠãŠãã ããã å
·äœçã«ã¯æåŸã®ãã®ã ããªãã®
ãšã¯ã¹ããŒããããã¡ãœããã¯ãããŒã«ã«ã¹ã³ãŒãã®å
åŒã¡ãœãããš
å®éã«ãšã¯ã¹ããŒããããã¡ãœããïŒã¢ãã¯ãããå ŽæïŒ
2017幎5æ31æ¥åå2:00ããnovalineã [email protected]ã¯æ¬¡ã®ããã«æžããŠããŸãã
@ainesophaurhttps ïŒ//github.com/ainesophaurãæ©èœããŠããŸããã
ã¢ãžã¥ãŒã«ïŒ
export const getMessage =ïŒnumïŒnumberïŒïŒstring => {
Her name is ${genName(num)}
è¿ã;
};
ãšã¯ã¹ããŒãé¢æ°genNameïŒnumïŒnumberïŒïŒstring {
'novaline'ãè¿ããŸãã
}ãã¹ãïŒ
é¢æ°mockFunctionsïŒïŒ{
const original = require.requireActualïŒ '../ moduleA'ïŒ;
æ»ã {
...ãªãªãžãã«ã
genNameïŒjest.fnïŒïŒïŒ=> 'emilie'ïŒ
}
} jest.mockïŒ '../ moduleA'ãïŒïŒ=> mockFunctionsïŒïŒïŒ; const moduleA = requireïŒ '../ moduleA'ïŒ;
describeïŒ 'ã¢ãã¯é¢æ°'ãïŒïŒ=> {itïŒ 't-0'ãïŒïŒ=> {
expectïŒjest.isMockFunctionïŒmoduleA.genNameïŒïŒãtoBeTruthyïŒïŒ;
}ïŒitïŒ 't-1'ãïŒïŒ=> {
expect(moduleA.genName(1)).toBe('emilie'); expect(moduleA.genName).toHaveBeenCalled(); expect(moduleA.genName.mock.calls.length).toBe(1); expect(moduleA.getMessage(1)).toBe('Her name is emilie'); expect(moduleA.genName.mock.calls.length).toBe(2);
}ïŒ;
}ïŒ;
ãã¹ãçµæïŒ
FAIL jest-examples / __ test __ / mock-function-0.spec.ts
âã¢ãã¯æ©èœâº t-1expect(received).toBe(expected) Expected value to be (using ===): "Her name is emilie" Received: "Her name is novaline" at Object.it (jest-examples/__test__/mock-function-0.spec.ts:22:35) at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
ã¢ãã¯é¢æ°
ât-0ïŒ1msïŒ
ât-1ïŒ22msïŒãã¹ãã¹ã€ãŒãïŒ1ã€å€±æãåèš1ã€
ãã¹ãïŒ1ã€å€±æã1ã€åæ Œãåèš2ã€
ã¹ãããã·ã§ããïŒåèš0
æéïŒ0.215ç§ãæšå®1ç§â
ããªããèšåãããã®ã§ããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/facebook/jest/issues/936#issuecomment-305091749 ããŸãã¯ãã¥ãŒã
ã¹ã¬ãã
https://github.com/notifications/unsubscribe-auth/AEeBdv6SafXlTtKo3DNeFWhbL6gV9l0Gks5r_QHjgaJpZM4IPGAH
ã
@ainesophaur ïŒ export class Session { }
è©ŠããŸããã ãããŠãããã¯ç§ã«ãšã£ãŠã¯ããŸããããŸããã
ç§ã«ãšã£ãŠæå¹ãªå¯äžã®ã¢ãããŒãã¯ãäžèšã®ã³ã¡ã³ãã«ãããŸããããã§ã¯ãç¢å°() =>
代ããã«function
æ§æã䜿çšãããŠããŸãã ããïŒ
export const session = {
saveSession: function() {
this.restartCheckExpiryDateTimeout();
},
restartCheckExpiryDateTimeout: () => {},
}
ããã¯Jest20.0.3ã«ãããŸã
ç§ããã£ãŠããããšã¯ãé¢æ°ã®constã©ãããŒãäœæããŠããããã®ã©ãããŒããšã¯ã¹ããŒãããããšã§ãïŒexport const fnsãªã©ïŒã 次ã«ãã¢ãžã¥ãŒã«å ã§fns.functionNameã䜿çšãããšãfns.functionNameé¢æ°ãjest.fnïŒïŒã§ããŸãã
ã¿ã€ãã¹ã¯ãªããã§èšè¿°ããããŠãŒã¶ãŒå®çŸ©ã¢ãžã¥ãŒã«ã®ã¢ãã¯é¢æ°ãäœæããå Žåãããã³ã¢ãã¯é¢æ°ãåŒã³åºãå Žåã¯ãé¢æ°ã®ã¢ãã¯ããŒãžã§ã³ãåŒã³åºããããã«ãã¬ããžã¬ããŒãã§ã«ããŒãããå ã®é¢æ°ã§ãã
ããšããšãã¹ãã§ã€ã³ããŒãããã2ã€ã®é¢æ°ããããŸãimport { getCurrentDate, getStartEndDatesForTimeFrame } from ./../_helpers/date';
ã芧ã®ãšããã getStartEndDatesForTimeFrame
ã¯getCurrentDate
äŸåããŠããŸãã 次ã®èšå®ã§ã¯ã getCurrentDate
ãã¹ããé©åã«æ©èœããã¢ãã¯ããŒãžã§ã³ã䜿çšããŸãã äžæ¹ãäœããã®çç±ã§getStartEndDatesForTimeFrame
ãã¹ãã¯ã¢ãã¯ãããgetCurrentDate
䜿çšããŸããããå
ã®å®è£
ã䜿çšããããããã¹ãã¯å€±æããŸãã ç§ã¯å€ãã®ç°ãªãã»ããã¢ãããè©ŠããŸããïŒ Date.now = jest.fn(() => "2017-11-16T20:33:09.071Z");
ããã«ããããæ©èœãããããšãã§ããŸããã§ãããäœãã¢ã€ãã¢ã¯ãããŸããïŒ
export const getCurrentDate = () => new Date();
export const getStartEndDatesForTimeFrame = (timeFrame) => {
...
const todayDate = getCurrentDate();
...
switch (timeframe) {
case TimeFrames.TODAY:
console.log(todayDate); // this always prints the real value in tests instead of the mocked one
start = new Date(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, 0, 0);
end = new Date(
todayDate.getFullYear(),
todayDate.getMonth(),
todayDate.getDate(), 23, 59, 59,
);
break;
...
return { start: start.toISOString(), end: end.toISOString() }
};
function mockFunctions() {
const original = require.requireActual('../../_helpers/date');
return {
...original,
getCurrentDate: jest.fn(() => '2017-11-16T20:33:09.071Z'),
}
}
jest.mock('../../_helpers/date', () => mockFunctions());
const dateModule = require.requireMock('../../_helpers/date');
describe('getCurrentDate', () => {
it('returns the mocked date', () => {
expect(dateModule.getCurrentDate()).
toBe('2017-11-16T20:33:09.071Z'); // this works well and returns the mocked value
});
});
describe('getStartEndDatesForTimeFrame', () => {
it('returns the start and end dates for today', () => {
expect(dateModule.getStartEndDatesForTimeFrame('today')).toEqual(
{ 'start': '2017-11-15T23:00:00.000Z', 'end': '2017-11-16T22:59:59.000Z' }
); // this one uses the original getCurrentDate instead of the mocked one :(
});
});
ãããã£ãŠã getStartEndDatesForTimeFrame
ã¯ãã¢ãã¯ãããæå»ã§ã¯ãªãçŸåšã®æå»ã䜿çšããããã倱æããŸãã
@ainesophaurã®ææ¡ã«åŸã£ãŠããªããžã§ã¯ãå ã®ãã¹ãŠã®é¢æ°ããšã¯ã¹ããŒãããããŒã«ã«ã¹ã³ãŒãã®å åŒã¡ãœããã®ä»£ããã«ãããã®ãšã¯ã¹ããŒãããããªããžã§ã¯ãã®ã¡ãœãããåŒã³åºãããšã§ããããæ©èœãããããšãã§ããŸããã
// imageModel.js
const model = {
checkIfImageExists,
getImageUrl,
generateImagePreview
}
export default model
async function checkIfImageExists(...) {}
async function getImageUrl() {}
async function generateImagePreview() {
// I am calling it as `model` object's method here, not as a locally scoped function
return model.getImageUrl(...)
}
// imageModel.test.js
import imageModel from './imageModel'
test('should mock getImageUrl called within the same file', async () => {
imageModel.getImageUrl = jest.fn().mockReturnValueOnce(Promise.resolve())
await imageModel.generateImagePreview()
expect(imageModel.getImageUrl).toBeCalled()
})
@miluoshiãããç§ãã§ããå¯äžã®æ¹æ³ã§ãã ãã®æ¹æ³ã䜿çšãããšãããã©ãŒãã³ã¹ã®äœäžãªã©ã¯ãããŸããïŒ ãã¹ãã§ããããã«ã³ãŒããå€æŽããã®ã¯ãééã£ãŠãããããã§ãã
ç§ã¯æ¬åœã«ãã æžãæ¹æ³ã欲ããã§ãïŒ
jest.mock('src/folder/file.func, () => {return 'whatever i want'})
ããã§éèŠãªã®ã¯.func
@miluoshi @Rdlenkeã³ãŒããååä»ããšã¯ã¹ããŒãã§æ§æãããŠããå Žåã¯ã import * as model
ããã model.generateImagePreview = jest.fn(() => Promise.resolve);
äžæžãããããšãã§ããŸãã
ãããsinonã§ã©ã®ããã«ãã¹ãããŸããïŒ åè¿°ã®ããã«ïŒhttps://github.com/facebook/jest/issues/936#issuecomment-214939935ãåç
§ïŒãESMã®åäœæ¹æ³ã«ããã func2
å
ã§func1
func2
ãã¢ãã¯ããããšã¯äžå¯èœã§ããç§ã¯å¿
ããããããåºæ¬ãšã¯èšããŸããã
ãã¶ããä»»æã®ãtestImportãé¢æ°ãèªã¿èŸŒãbabelmodãäœæã§ããŸãã
ãããŠãã³ãŒããæžãçŽããŠãã¢ãžã¥ãŒã«å
ã®é¢æ°ããšã¯ã¹ããŒãããåã«
ãã¹ãå®è¡ïŒ
2017幎12æ18æ¥æææ¥ã®ååŸ5æã«ãJimMoodynotifications @ github.comã¯æ¬¡ã®ããã«æžããŠããŸãã
ããªãã¯æ£ããã§ã@SimenBhttps ïŒ//github.com/simenb ãç§ã¯äœããå€æŽããŸãã
ç§ã®ãã¹ãã§ã¯ãSinonã«åãæ¿ããéã«ãåæ Œããããã«èŠããŸãã
ãããå ã«æ»ããŠãããŸã æ©èœããŠããŸããã åé¡ãªããšæããŸã
ããã¯è§£æ±ºãããŸãããâ
ããªããèšåãããã®ã§ããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/facebook/jest/issues/936#issuecomment-352488400 ããŸãã¯ãã¥ãŒã
ã¹ã¬ãã
https://github.com/notifications/unsubscribe-auth/AQRY9a5-s2_bjCWKNw5WiAJW-JeBf8W3ks5tBpoygaJpZM4IPGAH
ã
-
ãã¬ã³ã»ã¯ã¬ã¹ãŠã§ã«
å¥çŽéçºè
| Develer Limited
Eã¡ãŒã«ïŒ [email protected]
é»è©±ïŒ
ãŠã§ããµã€ãïŒ http ïŒ
ãã®é»åã¡ãŒã«ãå°å·ããåã«ãç°å¢ã«é
æ
®ããŠãã ãã
èŠåïŒã³ã³ãã¥ãŒã¿ãŠã€ã«ã¹ã¯é»åã¡ãŒã«ã§éä¿¡ãããå¯èœæ§ããããŸãã åä¿¡è
ãã®é»åã¡ãŒã«ãšæ·»ä»ãã¡ã€ã«ã§ãŠã€ã«ã¹ã®ååšã確èªããå¿
èŠããããŸãã
Develer Limitedã¯ããŠã€ã«ã¹ã«ãã£ãŠåŒãèµ·ãããããããªãæ害ã«ã€ããŠã責任ãè² ããŸããã
ãã®ã¡ãŒã«ã§éä¿¡ãããŸãã é»åã¡ãŒã«ã®éä¿¡ã¯ä¿èšŒã§ããŸãã
æ
å ±ãååãããããç Žæãããã倱ããããããå¯èœæ§ããããããå®å
šãŸãã¯ãšã©ãŒãçºçããŸããã
ç Žå£ããããé
ããŠå°çãããäžå®å
šãªããŸãã¯ãŠã€ã«ã¹ãå«ãŸããŠããã éãäž»
ãããã£ãŠããšã©ãŒãè±èœã«ã€ããŠã¯è²¬ä»»ãè² ããŸããã
é»åã¡ãŒã«éä¿¡ã®çµæãšããŠçºçãããã®ã¡ãã»ãŒãžã®å
容ã
èŠåïŒ Develer Limitedã¯åççãªäºé²çãè¬ããŠããŸããã
ãã®ã¡ãŒã«ã«ãŠã€ã«ã¹ãå«ãŸããŠããªãããšã確èªããŠãã ãããäŒç€Ÿã¯ãããåãå
¥ããããšãã§ããŸããã
ãã®é»åã¡ãŒã«ã®äœ¿çšã«èµ·å ããæ倱ãŸãã¯æ害ã«å¯Ÿãã責任ãŸãã¯
æ·»ä»ãã¡ã€ã«ã
Develer Limitedã¯ãã€ã³ã°ã©ã³ãããã³ãŠã§ãŒã«ãºã§ç»é²ãããæéäŒç€Ÿã§ãã |
äŒç€Ÿç»é²çªå·09817616 | ç»é²äºåæïŒSUITE 1 SECOND
FLOOR EVERDENE HOUSEãDEANSLEIGH ROADãããŒã³ãã¹ãã€ã®ãªã¹ãBH7 7DU
åé¿çãæäŸããŠããã
éåæã§åäœããäŸã圹ç«ã€ãšæãããå Žåã¯ã次ã®ããã«ããŸãã
//reportError.js
const functions = {};
functions._reportToServer = (error, auxData) => {
// do some stuff
};
functions.report = (error, auxData = {}) => {
if (shouldReportToServer()) {
functions._reportToServer(error, auxData);
}
};
export default functions;
// reportError.jest.js
import reportError from 'app/common/redux/lib/reportError';
reportError._reportToServer = jest.fn();
describe('test reportError', () => {
it('reports ERROR to server as as error', () => {
reportError.report(new Error('fml'), {});
expect(reportError._reportToServer).toHaveBeenCalledTimes(1);
});
});
@ jim-moodyåé¡ãæ£ããç解ããŠããã°ãããã¯ããªãã®äŸã§ããŸãããã¯ãã§ãïŒ
const spyOnExampleFunc2 = jest.spyOn(example, 'func2');
example.func1();
expect(spyOnExampleFunc2).toBeCalled();
ïŒãã®_only_ã¯ãäŸã®ããã«ãé¢æ°ãconstãšããŠãšã¯ã¹ããŒããããå Žåã«ã®ã¿æ©èœããŸãïŒ
@dinvladç§ã®ããŒããŒïŒ
@dinvladã®åçã«ç¶ããŠã jestãªããžã§ã¯ãããŒãžã®æ¬¡ã®ã¢ãã¯é¢é£ããã¥ã¡ã³ããã¢ãã¯é¢æ°ããŒãžã«è¿œå ãäŸã§è¡šç€ºããŸãã¯ãªã³ã¯ãããšãã¢ãã¯ã«é¢ããjestããã¥ã¡ã³ããæ¹åãããå¯èœæ§ããããšæããŸãã
ç§ã®ãŠãŒã¹ã±ãŒã¹ã¯ãjestã®æ°ãããŠãŒã¶ãŒãšããŠãmocha + sinon.jsã³ãŒããjestã«ç§»è¡ããããšã§ãã ç§ã¯ãã§ã«ã¹ãã€ãšæåŸ ãæã£ãŠããã®ã§ãããã¯ç°¡åã ãããšæããŸããã ãããããã®ã¹ã¬ãããèªã¿ãã¢ãã¯é¢æ°ã«é¢ããjestã®ããã¥ã¡ã³ããèªãã åŸããã®æ¹æ³ã§jestã䜿çšããã«ã¯ããã¹ããæžãçŽããããESMãBabelã詳现ã«ç解ãããããå¿ èŠããããããããªããšããå°è±¡ãåããŸããã
Jestã«æè¬ããŸã-ããã¯ç§ã®ãã¹ããæžã/ç解ããããããå®è¡ããã®ãéãããŸãã :)
ããã¥ã¡ã³ããæ確ã«ããPRã¯å€§æè¿ã§ãïŒ ð
ESã¢ãžã¥ãŒã«æ§æã§ç¹å®ã®ã¢ãžã¥ãŒã«ã®ã¿ãã¢ãã¯ããã«ã¯ã require.requireActualã䜿çšããŠå ã®ã¢ãžã¥ãŒã«ã埩å ããã¢ãã¯ããã¢ãžã¥ãŒã«ãäžæžãããŸãã
import { foo } from './example';
jest.mock('./example', () => (
...require.requireActual('./example'),
foo: jest.fn()
));
test('foo should be a mock function', () => {
expect(foo('mocked!')).toHaveBeenCalledWith('mocked!');
});
éããŸã«æããŸãããããã¯ç§ãåºããããæãç°¡åãªæ¹æ³ã§ãã @joshjgãžã®åžœåã®ãã³ãã
é·ãè°è«ã®ã©ããã§è¿·åã«ãªããŸããã質åããããŸãããé¢æ°ã®å®éã®å®è£ ãåŒã³åºããããã©ããããã¹ãããæ¹æ³ã¯ãããŸããïŒ
ç§ã®ç解ã§ã¯ã jest.fn()
ã䜿çšããå¿
èŠãããå Žåã¯å
ã®é¢æ°ããªãŒããŒã©ã€ãããŸããã䜿çšããªãå Žåã¯ãã³ã³ãœãŒã«ããjest.fn() function or a spy
ã§ããå¿
èŠããããšãããšã©ãŒã衚瀺ãããŸãã
ãªã¯ãšã¹ããæž¡ãããããã«ãŠã§ã¢ããã¹ãããããšããŠããã®ã§ããããã¢ãã¯ãããšããã¹ãŠã®ããžãã¯ã倱ãããããŒã¿ã次ã®ããã«ãŠã§ã¢ã«æž¡ãããŸããã ã€ã³ããŒãããŠã¢ãã¯ããªãå Žåããã®é¢æ°ãåŒã³åºãããããšããã¹ãã§ããŸããïŒ
jest.spyOn
ã䜿çšã§ããŸããïŒ ããã©ã«ãã§ã¯ãåºã«ãªãé¢æ°ãåŒã³åºããŸã
å©ããŠãããŠããããšããè©ŠããŸããããconsole.logãå ¥ããŠå°å·ããã®ã§åŒã³åºãããã®ã«ãåŒã³åºãããªãã£ãããšããã¹ãã§ç€ºãããŸããã
ãã¹ããã¡ã€ã«
import errorHandler from '../../controller/errorHandler'
describe('auth test', () => {
describe('test error: ', () => {
const test1 = jest.spyOn(errorHandler, 'handleClientError')
test('should return 400', (done) => {
request(app)
.post('/auth/error')
.then((res) => {
expect(res.statusCode).toBe(400)
expect(test1).toBeCalled()
done()
})
})
errorHandler
module.exports = {
handleClientError () {
console.log('err')
}
}
ã³ã³ãœãŒã«
console.log src/controller/errorHandler.js:10
err
â auth test ⺠test error: ⺠should return 400
expect(jest.fn()).toBeCalled()
Expected mock function to have been called.
18 | expect(res.statusCode).toBe(400)
> 19 | expect(test1).toBeCalled()
20 | done()
21 | })
22 | })
é¢æ°ã¯handleClientError
ãŸãã¯logError
ãšåŒã°ããŠããŸããïŒ
@WangHansenããªãã®äŸãããããªãã®ã³ãŒãã¯expect(errorHandler.handleClientError).toBeCalled() // > true
ã¯ãã§ã
@WangHansenããªã.mockImplementation()
ããªãã«jest.spyOn()
ïŒ ãžã£ã¹ãã³ããæ¥ã人ãšããŠãç§ã¯ãã®ãã³ãããžã£ã¹ãã³ã®ã¹ãã€ãšåãæ©èœãéæããããã«éèŠã§ããããšã«æ°ã¥ããŸããã äŸãã°
const mockModuleFunction = jest
.spyOn(module, 'function')
.mockImplementation(() => 'hello');
...
expect(mockModuleFunction.mock).toBeCalled();
mockImplementation()
䜿çšããªãå Žåã jest.spyOn()
ã¯ã¢ãã¯ïŒafaiuïŒã§ã¯ãªããªããžã§ã¯ããçæããå®éã«ã¯ãã€ãã£ãå®è£
ã«åŸããŸãã ãã€ãã£ãå®è£
ãç¶æããå¿
èŠãããå Žåã¯ã䜿çšãã䟡å€ããããããããŸãã
const moduleFunction = module.function;
jest.spyOn(module, 'function').mockImplementation(moduleFunction);
...
ãããå¿ èŠãã©ããã¯ããããŸããããæ©èœããã¯ãã§ãã
å ã®ãªã¯ãšã¹ãã«æ»ããŸã...
ã€ã³ããŒãã®åšãã«ãããã·ãã©ããããã ãã§ã¯ãããŸããã*ïŒ äŸãã°
import * as test from './ myfile.js';
constãã³ãã©ãŒ= {
/ **ã€ã³ã¿ãŒã»ããïŒããããã£ã®ååŸ* /
getïŒtargetãpropKeyãreceiverïŒ{
console.logïŒ GET ${propKey}
ïŒ;
123ãè¿ããŸãã
}ã
/** Intercepts: checking whether properties exist */
has(target, propKey) {
console.log(`HAS ${propKey}`);
return true;
}};
const p = new ProxyïŒtestïŒ;
4ïŒ24 PMã§ç«ã2018幎1æ30æ¥ã«ã¯ãããã¹ã»ããžãã[email protected]
æžããŸããïŒ
@WangHansenhttps ïŒ//github.com/wanghansenè¿œå ã§ããŸãã
.mockImplementationïŒïŒãjest.spyOnïŒïŒã«ïŒ ããæ¥ã誰ããšããŠ
ãžã£ã¹ãã³ãç§ã¯ãã®ãã³ãããšåãæ©èœãéæããããã«éèŠã ãšæããŸãã
ãžã£ã¹ãã³ã®ã¹ãã€ã äŸãã°const mockModuleFunction = jest
.spyOnïŒmoduleã 'function'ïŒ
.mockImplementationïŒïŒïŒ=> 'hello'ïŒ; ... expectïŒmockModuleFunction.mockïŒ.toBeCalledïŒïŒ;mockImplementationïŒïŒã䜿çšããªãå Žåãjest.spyOnïŒïŒã¯
ã¢ãã¯ïŒafaiuïŒã§ã¯ãªããå®éã«ã¯ãã€ãã£ãã«äŸåãããªããžã§ã¯ã
å®è£ ã ãã€ãã£ãå®è£ ãç¶æããå¿ èŠãããå Žåã¯ãå€åããã¯
䜿çšãã䟡å€ãããconst moduleFunction = module.function; jest.spyOnïŒmoduleã 'function'ïŒãmockImplementationïŒmoduleFunctionïŒ; .. ..
ãããå¿ èŠãã©ããã¯ããããŸããããæ©èœããã¯ãã§ãã
â
ããªããèšåãããã®ã§ããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/facebook/jest/issues/936#issuecomment-361648414 ããŸãã¯ãã¥ãŒã
ã¹ã¬ãã
https://github.com/notifications/unsubscribe-auth/AQRY9VXyHNYatwOOY6EV637WGQH9k5Plks5tP0I9gaJpZM4IPGAH
ã
-
ãã¬ã³ã»ã¯ã¬ã¹ãŠã§ã«
å¥çŽéçºè
| Develer Limited
Eã¡ãŒã«ïŒ [email protected]
é»è©±ïŒ
ãŠã§ããµã€ãïŒ http ïŒ
ãã®é»åã¡ãŒã«ãå°å·ããåã«ãç°å¢ã«é
æ
®ããŠãã ãã
èŠåïŒã³ã³ãã¥ãŒã¿ãŠã€ã«ã¹ã¯é»åã¡ãŒã«ã§éä¿¡ãããå¯èœæ§ããããŸãã åä¿¡è
ãã®é»åã¡ãŒã«ãšæ·»ä»ãã¡ã€ã«ã§ãŠã€ã«ã¹ã®ååšã確èªããå¿
èŠããããŸãã
Develer Limitedã¯ããŠã€ã«ã¹ã«ãã£ãŠåŒãèµ·ãããããããªãæ害ã«ã€ããŠã責任ãè² ããŸããã
ãã®ã¡ãŒã«ã§éä¿¡ãããŸãã é»åã¡ãŒã«ã®éä¿¡ã¯ä¿èšŒã§ããŸãã
æ
å ±ãååãããããç Žæãããã倱ããããããå¯èœæ§ããããããå®å
šãŸãã¯ãšã©ãŒãçºçããŸããã
ç Žå£ããããé
ããŠå°çãããäžå®å
šãªããŸãã¯ãŠã€ã«ã¹ãå«ãŸããŠããã éãäž»
ãããã£ãŠããšã©ãŒãè±èœã«ã€ããŠã¯è²¬ä»»ãè² ããŸããã
é»åã¡ãŒã«éä¿¡ã®çµæãšããŠçºçãããã®ã¡ãã»ãŒãžã®å
容ã
èŠåïŒ Develer Limitedã¯åççãªäºé²çãè¬ããŠããŸããã
ãã®ã¡ãŒã«ã«ãŠã€ã«ã¹ãå«ãŸããŠããªãããšã確èªããŠãã ãããäŒç€Ÿã¯ãããåãå
¥ããããšãã§ããŸããã
ãã®é»åã¡ãŒã«ã®äœ¿çšã«èµ·å ããæ倱ãŸãã¯æ害ã«å¯Ÿãã責任ãŸãã¯
æ·»ä»ãã¡ã€ã«ã
Develer Limitedã¯ãã€ã³ã°ã©ã³ãããã³ãŠã§ãŒã«ãºã§ç»é²ãããæéäŒç€Ÿã§ãã |
äŒç€Ÿç»é²çªå·09817616 | ç»é²äºåæïŒSUITE 1 SECOND
FLOOR EVERDENE HOUSEãDEANSLEIGH ROADãããŒã³ãã¹ãã€ã®ãªã¹ãBH7 7DU
@dinvlad @iampeterbanjo @SimenBãã¹ãŠã®ãååã«æ¹ããŠæè¬ããŸãããæ®å¿µãªãããããªããææ¡ããæ¹æ³ã¯ã©ããããŸããããŸããã§ããã é¢æ°ãnext(err)
圢åŒã§åŒã³åºãããŠããããã ãããã ããžãã¯ã¯ããªã¯ãšã¹ãã倱æããå Žåã return next(err)
åŒã³åºãããšã«ãã£ãŠerrorHandler
æž¡ãããŸãã console.log
ãè¿œå ãããšå°å·ããããããé¢æ°ãåŒã³åºãããŠããããšã¯ç¢ºãã§ãã ãããããã¹ãã¯ããã決ããŠåŒã³åºãããªãããšã瀺åããŠããŸã
@dinvladç§ã¯ããªãã®æ¹æ³ãè©ŠããŸãããããã¯jest.spyOnã®å
¬åŒããã¥ã¡ã³ãã«ãããšããªãmockImplementation
ãåŒã³åºãå¿
èŠãããã®ãââãå
ã®é¢æ°ããªãŒããŒã©ã€ãããå Žåã«ã®ã¿åŒã³åºãå¿
èŠãããã®ã§ã¯ãªãããšæã£ãŠããŸããã
@WangHansenã¯ããå ã®ã¡ãœããããªãŒããŒã©ã€ããããå Žåã«ã®ã¿å¿ èŠã«ãªãã®ã¯æ£ããã§ãã ç§ã¯ã¡ããã©ãããã®ç¶æ³ã®ãââãã®ã¢ã€ãã¢ãæããŠããŸããã
ãããããªãã®ããã«å€±æãããããããªã1ã€ã®çç±ã¯éåææ§ã§ãã ã¡ãœãããã³ãŒã«ããã¯ãPromisesïŒãŸãã¯async / awaitïŒã䜿çšããŠããå Žåã¯ããã¹ãã¡ãœãããçµäºããåã«ãæåŸ
å€ãå®éã«å®è¡ãããŠããããšã確èªããå¿
èŠããããŸãã ããã䞻匵ããããã®ç¹å¥ãªã¡ãœããexpect.assertions(N)
ããããŸãã ãŸããcallback / promiseså
ã®ã³ãŒããåŒã³åºãããåŸã«ã®ã¿æåŸ
ãå®è¡ãããããšã確èªããŠãã ããã ããªãã¯ãããèŠããšç¢ºä¿¡ããŠããŸãããåèã®ããã«ã httpsïŒ//facebook.github.io/jest/docs/en/asynchronous.html
@seibeljã説æããŠããããã«ãå éšã§äœ¿çšãããŠããfnsã
ç§ã®æèŠã§ã¯ããã¹ãã¯ããžãã¹ããžãã¯ã®å®è£ æ¹æ³ãæšé²ããã¹ãã§ã¯ãããŸããðïŒå°ãªããšããã®çšåºŠã§ã¯ãããŸããïŒ
ãã®ãããªæ¯ãèããåè«ã§å®è£ ããèšç»ã¯ãããŸããïŒ
ããã
ã¡ãã£ãšè°è«å
šäœã«é
ããŸããããè°è«å
šäœãèªãã§ãã ãã-ç§ã¯ãŸã ãããè¡ãããšãã§ããŸããã§ããã
@greypantsã®ææãªãœãªã¥ãŒã·ã§ã³ã¯ãå
ã®é¢æ°ããŸã åŒã³åºããŠãããããå®éã«ã¯æ©èœããŸããã§ããã
ãã®è°è«ã®éå§ä»¥æ¥ãäœãå€ãã£ãããšã¯ãããŸããïŒ ç§ã¯äœãã足ããªãã®ã§ããïŒ
@greypantsã®ãœãªã¥ãŒã·ã§ã³ãå°ãé©å¿ããã
import Module from './module'
import { getJSON } from './helpers'
jest.mock('./helpers', () =>
Object.assign(require.requireActual('./helpers'), {
getJSON: jest.fn()
})
)
test('should use the mock', async () => {
getJSON.mockResolvedValue('foo')
await expect(module().someAsyncThingThatUsesGetJSON()).resolves.toEqual('foo')
})
test('should use the actual module', () => {
expect(module().someFunctionThatUsesAHelper()).toBe(true)
})
ããã¯ãŸã ã¡ãã£ãšããããŒãªæããããŠãããã¥ã¡ã³ãã¯ããã»ã©åœ¹ã«ç«ã¡ãŸããã§ããã Jestãšãã®èåŸã«ããããŒã ã«æè¬ããŸãããå°ãªããšããå ¬åŒããœãªã¥ãŒã·ã§ã³ãå¿ èŠãªäžè¬çãªãŠãŒã¹ã±ãŒã¹ã®ããã§ãã
@sarahdayan ããããŠãããèå³ãæã£ãŠãããããããªã人-
ç§ã¯babel-plugin-rewireã䜿çšããããšã«ãªããŸããã
ãã®ãã©ã°ã€ã³ãèŠã€ããã®ã«å°ãæéãããããŸãããã 'ããããŒãæããªãããã«ååã«éŠå°Ÿäžè²«ãããœãªã¥ãŒã·ã§ã³ã§ããã
ã»ãšãã©ã®å Žåãã¢ãžã¥ãŒã«ãã1ã€ä»¥äžã®é¢æ°ãã¢ãã¯ããããããŸããã ã°ããŒãã«ãžã§ã¹ãã®ã¢ãã¯ã·ã¹ãã ã䜿çšããŠããå Žåã¯ã genMockFromModule
ãšrequireActual
ã䜿çšããŠãããå®çŸã§ããŸãã 次ã«äŸã瀺ããŸãã
// __mocks__/myModule.js
const moduleMock = jest.genMockFromModule('./../myModule');
// in most cases we don't want to mock `someFunction`
moduleMock.someFunction = jest.fn(
(...args) => require.requireActual('./../myModule').someFunction(...args)
)
module.exports = moduleMock;
ãã®ãœãªã¥ãŒã·ã§ã³ã§ã¯ãã¢ãžã¥ãŒã«å
šäœãã¢ãã¯ããããšãã«someFunction
å
ã®å®è£
ã䜿çšããŠãã¢ãžã¥ãŒã«ã®ä»ã®é¢æ°ã«ã¢ãã¯ã䜿çšã§ããŸãããŸãã mockImplementationOnce
ãŸãã¯mockImplementation
someFunction
é¢æ°ãã¢ãã¯ããããšãã§ããŸãã mockImplementation
APIã
äžèšã®ãã¹ãŠã®äŒè©±ãèªã¿ãŸãããã1ã€ã®è§£æ±ºçãããŸããããŸããã
ãã®ãã¹ãã±ãŒã¹ã®è§£æ±ºçããŸã æ¢ããŠããå Žåãçãã¯babel-plugin-rewireã§ãããã®ãã©ã°ã€ã³ã¯ã説æããã·ããªãªã±ãŒã¹ã解決ããããã®ãã®ã§ãã
ãã®libãèŠãŠãã ãããåŸã§ç§ã«æè¬ããŸãã
ãããã£ãŠãäžèšã®ã¹ã¬ããå šäœãèŠçŽãããšã次ã®ããã«ãªããŸãã
f
ã g
ã h
ãæã€ã¢ãžã¥ãŒã«m
ãããã g
ãšh
ãf
åŒã³åºããšããŸãã f
ãã¢ãã¯ããŠã g
ãšh
ãå®éã®f
ã§ã¯ãªãã¢ãã¯ãåŒã³åºãããã«ããŸãã æ®å¿µãªããã cpojerã説æããŠããããã«ã f
ãåžžã«exports
ãä»ããŠåŒã³åºãããªãéãããããçŽæ¥è¡ãã§ããŸããã ã¢ãžã¥ãŒã«ãTypeScriptã§ES6ã€ã³ããŒã/ãšã¯ã¹ããŒãæ§æã䜿çšããŠããå Žåãããã¯äžå¯èœã§ãïŒBabelã§ãåãããšãåœãŠã¯ãŸããšæããŸãïŒãf
ãå¥ã®ã¢ãžã¥ãŒã«m2
ãŸãã 次ã«ã m
ã«ã¯import {f} from 'm2'
ãããªã¹ããŒãã¡ã³ããããã g
ãšh
ãf
ãåŒã³åºããšãå®éã«ã¯m2.f
åŒã³åºããŸãã m2 = require('./m2')
ïŒBabel / TypeScriptã®ç¿»èš³ã¯ãã®ããã«ãªããŸãïŒã ããã«ãããgreypantsã§èª¬æãããŠããf
確å®ã«ã¢ãã¯ããããšãã§ããŸãã ã€ãŸããã¢ãžã¥ãŒã«ã®å¢çãè¶ããå Žåã«ã®ã¿ãåŒã³åºãã確å®ã«ã¢ãã¯ã§ããŸãã æ³šïŒ greypantsã®ãœãªã¥ãŒã·ã§ã³ã§ã¯ã次ã®ãšã©ãŒã¡ãã»ãŒãžãçæãããããã«ãªããŸããïŒã jest.mock()
ã®ã¢ãžã¥ãŒã«ãã¡ã¯ããªã¯ãã¹ã³ãŒãå€ã®å€æ°ãåç
§ã§ããŸãã-ç¡å¹ãªå€æ°ã¢ã¯ã»ã¹ïŒ__ assignãã ããã¯Jestã®ãã°ã ãšæããŸãã åé¿çãšããŠã以äžã«ç€ºãããã«Object.assign
ã䜿çšããŸããïŒ2ïŒã®äŸïŒ
~~~ js
//ã¢ãžã¥ãŒã«m.js
'./m2'ãã{f}ãã€ã³ããŒãããŸã
ãšã¯ã¹ããŒãé¢æ°gïŒïŒ{return'f returns '+ fïŒïŒ; };
//ã¢ãžã¥ãŒã«m2.js
ãšã¯ã¹ããŒãé¢æ°fïŒïŒ{return 'å®éã®f'; }
// test.js
ã€ã³ããŒã* as m from './ m'
jest.mockïŒ './ m2'ãïŒïŒ=> Object.assignïŒ
require.requireActualïŒ './ m2'ïŒã{
fïŒjest.fnïŒïŒãmockReturnValueïŒ 'MOCK'ïŒ
}ïŒïŒ;
testïŒ 'ã¢ãã¯'ãïŒïŒ=> {
expectïŒmgïŒïŒïŒãtoEqualïŒ 'fãMOCKãè¿ããŸãã'ïŒ;
}ïŒ;
~~~
ããããã¹ãããŠãããšãã«ãïŒ2649ã«ééããŸããããã¹ãå
ã§jest.mock
ãåŒã³åºããŠãå¹æã¯ãªããã°ããŒãã«ã¹ã³ãŒãã§åŒã³åºããšãä»ã®ãã¹ãã®åã«unmock
ãåŒã³åºãããšã¯ã§ããŸããã ãšãŠãããããã
ããããšãïŒïŒ @sarahdayan
ãã°ãããããæ¢ããŠããŸãã
ããã¥ã¡ã³ããäžè¶³ããŠããå ŽåãPRã¯ãã€ã§ãããããæ確ã«ããããšãæè¿ããŸãð
çããããã«ã¡ã¯ïŒ
ç§ã¯å°ãéãã§ããã®åé¡ã解決ããããã«æ¬¡ã®ã¢ã€ãã¢ãæãã€ããŸããïŒ
// m1.js
export const f = () => "original f"
// __mocks__/m1.js
const originalM1 = require.requireActual("../m1");
// set the original as a prototype
let mockModule: any = Object.create(originalM1);
const __setMock = (name, value) => {
mockModule[name] = value;
};
const __removeMock = (name) => {
Reflect.deleteProperty(mockModule, name);
};
// enhance the mocked module to allow overriding original exports
module.exports = Object.assign(mockModule, { __setMock, __removeMock });
// m1.test.js
import { f } from "./m1";
jest.mock("./m1");
test("mocking stuff", () => {
// here nothing is mocked - the original module is used
expect(f()).toBe("original f");
// override the export f of the module
require("./m1").__setMock("f", () => "mocked f");
expect(f()).toBe("mocked f");
// set it back to the original
require("./m1").__removeMock("f");
expect(f()).toBe("original f");
//override with another value
require("./m1").__setMock("f", () => "another mocked f");
expect(f()).toBe("another mocked f");
});
ç§ã®2ã»ã³ãïŒ
ç§ã¯å€ãã®è§£æ±ºçããã¹ãããŸããïŒãããã®ãã¹ãŠã§ã¯ãªãã«ããŠãïŒãããŠç§ã®ããã«åããå¯äžã®ãã®ã¯ããã§ãïŒåè«23ïŒïŒ
// importedModule.js
export const funcB = () => {
return "not mocked";
};
export const funcA = () => {
return mockProxy.funcB(); // this works but it's soooo hacky
};
export const mockProxy = {
funcB
};
// moduleToTest.js
import { funcA } from "./moduleImported.js";
export default function() {
return funcA();
}
// test
let moduleImported = require("./moduleImported.js");
moduleImported.mockProxy.funcB = jest.fn(() => "mocked");
const funcToTest = require("./moduleToTest.js").default; // or import
it("should return mocked", function() {
expect(funcToTest()).toBe("mocked");
});
ç§ã¯ãããããããšããã®ã¯è¯ãèãã§ã¯ãªããšããçµè«ã«éããŸããïŒ
test.js
ã¯ã importedModule.js
å®è£
ã®è©³çŽ°ã«ã€ããŠããç¥ã£ãŠããŸããmockProxy
ãèŠãŠã importedModule.js
誰ãããããæ©èœãã解決çãèŠã€ããŸãããïŒ
ç§ã䜿çšããŠãããã®ïŒ
"jest": "^21.2.1",
"jest-cli": "^21.2.1",
@jamesoneãããèªãã ããšããããŸãã
@thomaskempelã®åçã«åºã¥ããŠãããã¯ç§ã«ãšã£ãŠã¯
ç§ã®å Žåãnode_modulesã®äŸåé¢ä¿ãã¢ãã¯ãããã£ãã®ã§ããshared-componentsããšåŒã³ãŸãããã å€æ°ã®ååä»ãã³ã³ããŒãã³ãããšã¯ã¹ããŒãããŸãã ãããã®ååä»ããšã¯ã¹ããŒãã®ããã€ãã ããã¢ãã¯ããæ®ãã¯æ¬ç©ã®ãŸãŸã«ããŠããããã£ãã®ã§ãã
ãããã£ãŠã __mocks__/shared-components.js
ã«ã¯æ¬¡ã®ãã®ããããŸãã
const original = require.requireActual('shared-components');
module.exports = {
...original,
moduleNameToOverride: jest.fn().mockImplementation(() => {
return 'whatever';
}),
}
ç§ã®å Žåãå®è£ ãã¹ã¿ãåããŠããã ããŸãããã°ãããã¯å°æ¥èª°ããå©ããã§ãããã
ç§ã¯æè¿åãåé¡ã«çŽé¢ããŸããããã®ã¹ã¬ããã§ã®äŒè©±ã¯ç§ãããããç解ããã®ã«åœ¹ç«ã¡ãŸããããããŠç§ã¯ããã«ç§ã®çºèŠãèŠçŽããŸããhttps://medium.com/@DavideRama/mock -spy-exported-functions-within-a-single- module-in-jest-cdf2b61af642
@qwertieã®ãœãªã¥ãŒã·ã§ã³ã«è§Šçºããã
mockGet = jest.fn()
jest.mock('my-module', () => ({
...jest.requireActual('my-module'),
get: mockGet
}))
React.lazy
åäœãã@MajorBreakfast ïŒ
const mockLazy = jest.fn();
jest.mock('React', () => ({
...jest.requireActual('React'),
lazy: mockLazy
}));
ç§ã¯ãŸã ReferenceError: React is not defined
ååŸããŸãã
ç¬ç«ãããšã¯ã¹ããŒãæ±çšã¢ãžã¥ãŒã«ãã¢ãã¯ããã«ã¯ïŒ
ããã©ã«ãã®ãšã¯ã¹ããŒãã®äžéšã§ããåã
ã®é¢æ°ããã¹ãŠãã¡ã€ã«ãããšã¯ã¹ããŒãããŸãã
äŸïŒ
dataDao.js
é¢æ°getDataïŒïŒ
é¢æ°setDataïŒïŒ
é¢æ°deleteDataïŒïŒ
ãšã¯ã¹ããŒã{getDataãsetDataãdeleteData}
ããã§ãããã©ã«ãã®ååä»ãã§ããã¡ã€ã«ããjestãã¹ãã«ãã¹ãŠã®é¢æ°ãã€ã³ããŒãã§ããŸãã
dataDao.spec.js
import * as dataDao from '../ dataDao';
//ã€ã³ããŒãæã«å²ãåœãŠãããããã©ã«ãåãåç
§ããã¢ãžã¥ãŒã«ãã¹ãã€ããŸã
jest.spyOnïŒdataDaoã 'getData'ïŒ
jest.spyOnïŒdataDaoã 'setData'ïŒ
jest.spyOnïŒdataDaoã 'deleteData'ïŒ
@vchinthakunta ãåäœããå¯èœæ§ããããŸããããšã¯ã¹ããŒã/ã€ã³ããŒãæ§æã®äž»ãªç®çã«éåããŠããããã§ããä»ã®ã¢ãžã¥ãŒã«ã¯ããä»ããŠç¹å®ã®ã¡ãœãããŸãã¯ããŒã¿ãã£ãŒã«ããã€ã³ããŒãã§ããªããªããŸãã
import { justThisThing } from 'someModule';
ç§ã¯ããã«äœããæ¬ ããŠããŸããïŒ
React.lazy
åäœãã@MajorBreakfast ïŒconst mockLazy = jest.fn(); jest.mock('React', () => ({ ...jest.requireActual('React'), lazy: mockLazy }));
ç§ã¯ãŸã
ReferenceError: React is not defined
ååŸããŸãã
ãReactãã¯ã€ã³ããŒããåç §ããŠããã®ã§ãããã§ã¯å°æåã«ããå¿ èŠããããšæããŸããïŒ
jest.mock('react'...)
ç§ã¯ããã§èŠãä»ã®ãœãªã¥ãŒã·ã§ã³ãããç°¡åãªä»¥äžã䜿çšããŠã³ãŒããåäœãããŸããã require
ããã default
ãšã¯ã¹ããŒããèšå®ãããããå¿
èŠã¯ãããŸããã
helpers / Navigation.js
export const initHeader = () => {
// initialise header
...
}
...
export const anotherHelperFunction = () => {
// do stuff
...
}
Navigation.jsã䜿çšããã³ã³ããŒãã³ã
import { initHeader } from '../helpers/navigation';
jest.mock('../helpers/navigation');
...
describe('Test component', () => {
it('should reinitialise header', () => {
const mockHeaderInit = jest.fn();
initHeader.mockImplementation(mockHeaderInit);
const component = mountComponent(mockProps);
component.simulate('click');
expect(mockHeaderInit).toBeCalled();
}
}
mockGet = jest.fn() jest.mock('my-module', () => ({ ...jest.requireActual('my-module'), get: mockGet }))
ReferenceError: mockGet is not defined
4 | const mockGet = jest.fn();
5 | jest.mock('./browserStorage', () => ({
6 | ...jest.requireActual('./browserStorage'),
> 7 | get: mockGet,
| ^
8 | }));
jest.mock
ãæã¡äžããããŠããå Žåã¯ã doMock
ãã
jest.mock('./browserStorage', () => ({
...jest.requireActual('./browserStorage'),
get: jest.fn(),
}));
const {get: mockGet} = require('./browserStorage');
ããã¯ããããåé¡ã®ããã§ãã jestã®ããã¥ã¡ã³ãã«ããã«ã€ããŠäœããããŸããïŒ
ããã§ãåãã¢ãžã¥ãŒã«å ã®é¢æ°ãã¢ãã¯ããããã®è§£æ±ºçã¯ãã
次ã®æ¹æ³ã§ããŸããããŸãããããªãã¯ã¯ããã¹ãã®æåŸã«ã¢ãã¯ãããé¢æ°ããªã»ããããããšã§ãã
ãã®äŸã®ã¢ãã¯ã¯ãjsonwebtokenã¢ãžã¥ãŒã«ã®é¢æ°ãæ€èšŒããŸãã
test('perform my test', async () => {
// save the real jwt.verify function
const verify = jwt.verify
// mock it.
jwt.verify = jest.fn().mockReturnValue({ sub: 0 })
// do the test
...
// set the real function back.
jwt.verify = verify
})
次ã®æ¹æ³ã§ããŸããããŸãããããªãã¯ã¯ããã¹ãã®æåŸã«ã¢ãã¯ãããé¢æ°ããªã»ããããããšã§ãã
ãã®äŸã®ã¢ãã¯ã¯ãjsonwebtokenã¢ãžã¥ãŒã«ã®é¢æ°ãæ€èšŒããŸããtest('perform my test', async () => { // save the real jwt.verify function const verify = jwt.verify // mock it. jwt.verify = jest.fn().mockReturnValue({ sub: 0 }) // do the test ... // set the real function back. jwt.verify = verify })
const verify
ã©ãã§äœ¿çšããŠããŸããïŒ ãšã«ãããããã¯ã¢ãã¯ãããé¢æ°ããšã¯ã¹ããŒããããconsté¢æ°ã§ãªãå Žåã«ã®ã¿æ©èœããŸã
ããã§ã_åãã¢ãžã¥ãŒã«å ã§_é¢æ°ãã¢ãã¯ããããã®è§£æ±ºçã¯ãããŸããïŒ
å€ãã®æ€çŽ¢ãè¡ã£ãåŸããã®åé¡ã®è§£æ±ºçã¯ãé¢æ°ãšã¢ãã¯ãåç §ã§ããåäžã®ãªããžã§ã¯ãã«ãšã¯ã¹ããŒããä¿åããããšã§ãã 以äžã®èšäºã¯ãã¹ãŠåãã³ã³ã»ã³ãµã¹ã«éããŸããã
https://github.com/facebook/jest/issues/936#issuecomment -438975674
https://medium.com/@qjli/how -to-mock-specific-module-function-in-jest-715e39a391f4
https://luetkemj.github.io/170421/mocking-modules-in-jest
ã³ãŒãã§å®è¡å¯èœã§ããã°ãããããã¹ãŠã®åé¡ãå®å šã«æé€ããç®çã®ã³ãŒãã®ãã¹ããéåžžã«ç°¡åã«ããå¥ã®ãœãªã¥ãŒã·ã§ã³ã«ã€ããŠèª°ãèšåããŠããªãã®ã¯é©ãã§ãã
_ã¢ãã¯ãããåäžã®é¢æ°ãç¬èªã®ã¢ãžã¥ãŒã«ã«ç§»åããŸãã_
çå£ã«ã ã¢ãžã¥ãŒã«ã®å éšãä»ã®å éšãšã¯å¥ã«ãã¹ãããå¿ èŠãããããã«ã¢ãžã¥ãŒã«ãäœæãããŠããå Žåãã»ãŒç¢ºå®ã«ãã¯ã©ã¹ã¯åäžè²¬ä»»ã®ååã«éåããŠããŸãïŒã¯ããå®éã®ã¯ã©ã¹ã§ã¯ãããŸããããã¢ãžã¥ãŒã«ã¯ã¯ã©ã¹ã®ããã«æ©èœããŠããŸããã¢ãžã¥ãŒã«ã¯ã³ãŒãã®ãŠãããã³ã³ããã§ãïŒã ãã®åžç€ãåå²ããããŒã ãããªãã¯å¿ èŠãªãã®ãããããããšãã§ããŸãã
ã¢ãã¯ãããé¢æ°ãäžé£ã®ãã©ã€ããŒãç¶æ ã«äŸåããŠããå Žåã§ããããã¯ã¢ãžã¥ãŒã«ãäœããã®æ¹æ³ã§åå²ããªãçç±ã«ã¯ãªããŸããã ãããå€ãã®å éšç¶æ ã«äŸåããŠãããšããäºå®ã¯ãç§ã«ã¯ãã¢ãžã¥ãŒã«ã®æžå¿µãæ確ã«èããããŠããªãããšãæå³ããŸãã ãããããåå²ãã3çªç®ã®ã¢ãžã¥ãŒã«ããããŸããããã¯ãåŒæ°ãšããŠæž¡ãããšãã§ãããããçš®ã®ããŒã¿ã¯ã©ã¹ãŸãã¯DTOãè¡šããŸãã
ãŸãããã¹ãã®ããã ãã«ãã©ã€ããŒããªé¢æ°ããšã¯ã¹ããŒãããŠããŸããïŒ å€éšã³ãŒããã¢ãã¯ãããé¢æ°ãçŽæ¥åŒã³åºãã ãã§ãªããããèªäœãåŒã³åºãå¿ èŠã®ããä»ã®é¢æ°ãåŒã³åºãã®ã¯ãªãã§ããïŒ ããã§äœããã®åæãèµ·ãã£ãŠããã«éããããŸããã ãã¶ããã¢ãã¯ãããé¢æ°ã¯ãã®ãŸãŸã«ããŠããå¿ èŠããããŸããããã¹ãŠã®é¢æ°ãååã«åå²ããååãåé€ããŠå¥ã®ã¢ãžã¥ãŒã«ã«å ¥ããå¿ èŠããããŸãã ããªãã¯ãã®èããç解ããŸãã
ãã¹ããéåžžã«å°é£ã«ãªããšãã»ãšãã©ã®å Žåããªãã¡ã¯ã¿ãªã³ã°ãå¿ èŠãªå åã§ã...
ãã¹ãã®äžæ£è¡çºã¯å¿ èŠãããŸããïŒ
const tomfoolery = require('tomfoolery'); // no longer required
ãã®ã¹ã¬ãããèªã¿ãææ¡ããããœãªã¥ãŒã·ã§ã³ããã¹ãããåŸã§ãããããæ©èœãããããšã¯ã§ããŸããã ç§ãèªãã ããšãããäœäººãã®äººã ããã®äœåãäœããŸããããç§ã¯ã©ã®ããã«ç解ããããšãã§ããŸããã
ãã¹ãã«åæ Œããããã«æ¬¡ã®äŸã«è¿œå ããå¿ èŠãããã³ãŒãã誰ãã«æããŠããããŸããïŒ
// a.js
export const foo = () => 'foo-' + bar()
export const bar = () => 'bar'
// a.test.js
import {
foo,
bar
} from './a'
describe('foo', () => {
it('should return foo-MOCKED_BAR', () => {
expect(foo()).toBe('foo-MOCKED_BAR')
})
it('should have the mocked implementation of bar', () => {
expect(bar()).toBe('MOCKED_BAR')
})
})
describe('bar', () => {
it('should have the original implementation of bar', () => {
expect(bar()).toBe('bar')
})
})
describe('foo and bar together', () => {
it('should have the original implementation of both', () => {
expect(foo()).toBe('foo-bar')
})
})
ããããšãïŒ
lodash.randomã®ãããªåäžã®lodashã¡ãœããã®ã¿ãã¢ãã¯ãããã£ãã®ã§ã次ã®æ¹æ³ã§ç°¡åã«å®è¡ã§ããŸããã
module.js
const lodash = require('lodash');
module.exports = function() {
return lodash.random();
}
test.js
const lodash = require('lodash');
const module = require('./module.js);
it('mocks lodash', () => {
jest.spyOn(lodash, 'random').mockImplementationOnce(() => {
return 2;
});
expect(module()).toEqual(2)
});
ã圹ã«ç«ãŠã°å¹žãã§ã:)
typescriptã䜿çšããããŒã ã§æ©èœããã®ã¯ãé¢æ°ãçŽæ¥ãšã¯ã¹ããŒãããã®ã§ã¯ãªãããšã¯ã¹ããŒãããconst
ãäœæããããš
åäœããªãïŒ
export function doSomething(a, b) {}
åãïŒ
export const doSomething = function (a, b) {}
@arbielskã®ããã«ãšã¯ã¹ããŒããå€æŽããŸãããåäœããŸãïŒ ãããã2çš®é¡ã®ãšã¯ã¹ããŒãã®éãã¯äœã§ãã...
@dgrcodeäŸã®è§£æ±ºçãèŠã€ããããšããããŸããïŒ ç§ã®ç¥ãéããããªããããããšããŠããããšã¯ãJestãä»ããã¢ãã¯ã§ã¯ãµããŒããããŠããŸããã å
·äœçã«ã¯ãã¢ãã¯ã€ã³ã¯åºæ¬çã«ã€ã³ããŒããåé
ç·ããŠãã¢ãžã¥ãŒã«ã®å€éšãã¥ãŒã«ã¢ãã¯ãããã¡ãœããã衚瀺ãããããã«ããããšfoo
ãšbar
ãåãã¢ãžã¥ãŒã«å
ã«ããããã foo
ã®bar
ã®ãã¥ãŒãã¢ãã¯ã¢ãŠãããããšã¯ã§ããŸããã
ç§ã¯ããªãã®éžæè¢ã次ã®ããããã§ãããšä¿¡ããŠããŸãïŒ
1ïŒ foo
ãbar
ãå«ãã¢ãžã¥ãŒã«ãã€ã³ããŒãããããã«ãã³ãŒããåç·šæããŸã
2ïŒ babel-plugin-rewireã䜿çšãã
誀解ããŠããå Žåã¯èšæ£ããŠãã ããïŒ
å°ãç°ãªãèŠä»¶ããããŸããã1ã€ã®é¢æ°ãé€ããŠã¢ãžã¥ãŒã«å šäœãã¢ãã¯ãããã£ãã®ã§ãã @MajorBreakfastã®ãœãªã¥ãŒã·ã§ã³ãåºçºç¹ãšããŠäœ¿çšããŠãç§ã¯æ¬¡ã®ããšãæãã€ããŸããã
jest.mock('my-module', () => ({
...jest.genMockFromModule('my-module'),
myFunction: jest.requireActual('my-module').myFunction
}))
@dgrcodeäŸã®è§£æ±ºçãèŠã€ããããšããããŸããïŒ ç§ã®ç¥ãéããããªããããããšããŠããããšã¯ãJestãä»ããã¢ãã¯ã§ã¯ãµããŒããããŠããŸããã å ·äœçã«ã¯ãã¢ãã¯ã€ã³ã¯åºæ¬çã«ã€ã³ããŒããåé ç·ããŠãã¢ãžã¥ãŒã«ã®å€éšãã¥ãŒã«ã¢ãã¯ãããã¡ãœããã衚瀺ãããããã«ããããšã ãšæããŸãã ãã ãããã®äŸã§ã¯ã
foo
ãšbar
ãåãã¢ãžã¥ãŒã«å ã«ãããããfoo
ã®bar
ã®ãã¥ãŒãã¢ãã¯ã¢ãŠãããããšã¯ã§ããŸãããç§ã¯ããªãã®éžæè¢ã次ã®ããããã§ãããšä¿¡ããŠããŸãïŒ
foo
ãbar
ãå«ãã¢ãžã¥ãŒã«ãã€ã³ããŒãããããã«ãã³ãŒããåç·šæããŸã- babel-plugin-rewireã䜿çšãã
誀解ããŠããå Žåã¯èšæ£ããŠãã ããïŒ
ããã¯å®éã«ç§ã®å Žåã§ãã
ã¢ãžã¥ãŒã«ãã¢ãã¯ããæ¹æ³ã«ã€ããŠã®ç§ã®ç解ã¯ãã¹ãŠå°ç¡ãã«ãªããŸããð€Šââ
åºæ¬ç
2ã€ã®é¢æ°ãåãã¢ãžã¥ãŒã«å
ã«ãããçžäºã«åŒã³åºãå Žå
foo
ãbar
åŒã³åºããŠããå Žå
function bar() {
return 'some-result'
}
function foo(){
return bar() // <-- the function I want to mock
}
bar
ãæ°ãããã¡ã€ã«ã«å
¥ããŸãïŒã¢ãã¯ãããŸãïŒ
bar
ã¡ãœãããæ°ãããã¡ã€ã«ã«ç§»åããŸãããããã§ãäžèšã®äŸã®å€ãã䜿çšã§ããããã«ãªããŸããã
@ yoni-abtechã«æè¬ããŸãð€£
ãã®ã¹ã¬ããå šäœãèªãã§äœåºŠããã¹ãããåŸã®ç§ãèŠãæ¹æ³ã«ã¯ã3ã€ã®ãªãã·ã§ã³ããããŸãã
const
ã䜿çšããŠãã¹ãŠã®é¢æ°ã宣èšããŸãããã«ã¯ã宣èšãããé¢æ°åŒã®äœ¿çšã矩åä»ããå¿
èŠããããŸãã 幞ããªããšã«ã func-style
eslintã«ãŒã«ãããªããåãæ»ããŸããã
export const
䜿çšãããšã _same_ã¢ãžã¥ãŒã«å
ããä»ã®é¢æ°ââã«ãã£ãŠäœ¿çšãããspyOn
é¢æ°ã䜿çšã§ããŸãã
// hello.js
export const message = () => {
return 'Hello world';
}
export const foo = () => {
return message();
}
// hello.test.js
import * as testModule from './hello.js';
describe('test spyon with function expressions', function () {
afterAll(() => {
jest.restoreAllMocks();
});
it('should NOT mock message in foo', function () {
const actual = testModule.foo();
expect(actual).toBe('Hello world');
});
it('should mock message in foo', function () {
jest.spyOn(testModule, 'message').mockReturnValue('my message');
const actual = testModule.foo();
expect(actual).toBe('my message');
expect(testModule.message).toHaveBeenCalledTimes(1);
});
});
rewire
babelãã©ã°ã€ã³ã䜿çšããé¢æ°åŒã®äœ¿çšã矩åä»ããããªãå ŽåïŒã€ãŸãã const
ïŒãããã¯è¯ãã¢ãããŒããããããŸããã
ããã«ãããåãã¢ãžã¥ãŒã«ããé¢æ°ã_åé
ç·_ ïŒå¥åã¢ãã¯ïŒããããšãã§ããŸãã ã³ãŒãã¯ä»¥äžã®ããã«èŠãããšæ³åã§ããŸãããããã¹ãããŠããŸããã ãŸãã圌ãã®ããã¥ã¡ã³ããããã¢ãžã¥ãŒã«ãããšã¯ã¹ããŒããããŠããªãåãã¢ãžã¥ãŒã«å
ã®é¢æ°ãåé
ç·ã§ããããã§ãðã message
é¢æ°ããšã¯ã¹ããŒãããã«ä»¥äžã®äŸãæ³åããŠãã ããã
äŸïŒ
// hello.js
export function message() {
return 'Hello world';
}
export function foo() {
return message();
}
// hello.test.js
import * as testModule from './hello.js';
describe('test rewire api', function() {
it('should NOT mock message in foo', function () {
const actual = testModule.foo();
expect(actual).toBe('Hello world');
});
it('should mock message in foo', function () {
testModule.__RewireAPI__.__Rewire__('message', jest.fn().mockReturnValue('my message'));
const actual = testModule.foo();
expect(actual).toBe('my message');
expect(testModule.message).toHaveBeenCalledTimes(1);
testModule.__RewireAPI__.__ResetDependency__('message');
});
});
äŸã«ã€ããŠã¯ãããã¥ã¡ã³ããåç §ããŠãã ããã
泚ïŒããã«ã®è»¢åãå¿ èŠã§ã
ãã®ãªãã·ã§ã³ã¯æã奜ãŸãããããŸããããéåžžã®mock
æ©èœã§åé¡ãªãæ©èœããããšã¯æããã§ãã
PSïŒãã®ãã¬ããã¯éåžžã«åçºçã§ããã°ãã°é¢çœããã®ã§ãããããã®æŠèŠãä»ã®äººãã¹ã¬ããå šäœãèªãå¿ èŠæ§ã軜æžããããšãé¡ã£ãŠããŸãã âïž
@nickofthymeã«æè¬ã
@nickofthymeããªãã®option 1
ã¯ç§ã®ã¢ããªãšcreate react app
äž¡æ¹ã§å€±æããŸãïŒ
FAIL src/hello.test.js
test spyon with function expressions
â should NOT mock message in foo (3ms)
â should mock message in foo (6ms)
â test spyon with function expressions ⺠should mock message in foo
expect(received).toBe(expected) // Object.is equality
Expected: "my message"
Received: "Hello world"
17 | const actual = testModule.foo();
18 |
> 19 | expect(actual).toBe("my message");
| ^
20 | expect(testModule.message).toHaveBeenCalledTimes(1);
21 | });
22 | });
at Object.toBe (src/hello.test.js:19:20)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 passed, 2 total
Snapshots: 0 total
Time: 1.848s
Ran all test suites related to changed files.
@danielhusarããªãã¯æ£ããããã§ãã ç³ãèš³ãããŸãããããããCRAã§ãã¹ãããå¿ èŠããããŸããã
ãªãã·ã§ã³1ã§èª¬æããã¢ãã¯ãããã§æ©èœããyarn test:hello
ã¹ã¯ãªããã䜿çšããŠãã¹ãããŸãã
> yarn test:hello
yarn run v1.16.0
$ jest --config=jest.config.js -t=hello --verbose
PASS src/hello/hello.test.ts
test hello
â should NOT mock message in foo (3ms)
â should mock message in foo (1ms)
Test Suites: 1 skipped, 1 passed, 1 of 2 total
Tests: 1 skipped, 2 passed, 3 total
Snapshots: 0 total
Time: 1.392s
Ran all test suites with tests matching "hello".
âš Done in 2.36s.
ts-jest
ã䜿çšããŠã«ã¹ã¿ã jest.config.js
ãã¡ã€ã«ã䜿çšãã react-scripts
ä»ããã«ã jest --config=./jest.config.js
çŽæ¥åŒã³åºãå¿
èŠããããŸãã react-scripts
ã§jestãã©ã®ããã«æ§æãããŠãããã¯ããããŸããããäœããã®æ¹æ³ã§æ§æãæŽæ°ããæ¹æ³ããããšæããŸãã
ãã®ä¿®æ£ã«ããã *.css
*.svg
ãã¡ã€ã«ãšApp.tsx
ãšã©ãŒã¯ç¡èŠããŠãã ããã
ãããæ©èœãããããã«è¡ãå¿
èŠãããç¹å¥ãªããšã¯ãããŸããïŒ
ç§ã¯ããªãæšæºçãªã»ããã¢ããïŒtsãªãïŒãæã£ãŠããŠããã®ãŸãŸã§ã¯æ©èœããªããšæããŸãã
ä»å€ã¯ããå°ãèŠãŠããããå¯èœãã©ããã確èªããŸãã
@danielhusaræšå€èª¿ã¹ã䜿ãããœãªã¥ãŒã·ã§ã³ãåŸãããšãã§ããŸããã§ããã éèŠãªã®ã¯ãCRAãpackage.json#jest
ãªãŒããŒã©ã€ãã§ããjestæ§ætransformer
package.json#jest
ã§ãã JSãšTSãã¡ã€ã«ã䜿çšããŠtranspiledããbabel-jest
ãã react-scripts
ãããã¯äœ¿çšããŠããããªãã.babelrc
èšå®ãã¡ã€ã«ãããèšå®ãtest
ENV圌ããã©ã®ã»ããreact-scripts test
ããã
ãã£ãšæ·±ãæãäžãããããããã®ã«ãä»ã¯æéããªãã
ããŒããç§ã¯ãŸã ãããæ©èœãããã®ã«å°ãèŠåŽããŠããŸãïŒç§ã®ã«ã¹ã¿ã ã»ããã¢ããã§ã¯ãcraã§ã¯ãããŸããïŒã
ïŒjestãšbabel-jestã®äž¡æ¹ã®ææ°ããŒãžã§ã³ïŒ
ããã¯ç§ã®åè«ã®èšå®ã§ãïŒ
module.exports = {
name: 'my-app',
testURL: 'http://localhost/',
setupFiles: ['<rootDir>/setup-jest.js'],
setupFilesAfterEnv: ['<rootDir>/setup-test.js'],
testMatch: ['**/__tests__/**/*.test.js?(x)', '**/?(*.)+(spec|test).js?(x)'],
testEnvironment: 'jest-environment-jsdom-fifteen',
snapshotSerializers: ['enzyme-to-json/serializer'],
globals: {
ENV: 'test',
},
transform: {
'^.+\\.[t|j]sx?$': 'babel-jest',
},
};
ãããŠç§ã®babelrcïŒ
{
"presets": [
"@babel/react",
["@babel/env", {
"corejs": "3",
"useBuiltIns": "entry",
"loose": true,
"exclude": [
"es.string.split"
]
}],
"@babel/flow"
],
"plugins": [
"array-includes",
"lodash",
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-class-properties",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-proposal-optional-chaining"
],
"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}
ãªãã·ã§ã³1ã§èŠåŽããŠãã人ã«ãšã£ãŠã¯ã () => (expression)
é¢æ°ã®ä»£ããã«() => { return expression }
ã䜿çšããããšãéèŠã§ãã
ãªãã·ã§ã³1ã次ã®ããã«å€æŽããããšã§ãæ©èœããããã«ãªããŸããã
import * as test from './test';
export const message = () => {
return 'Hello world';
}
export const foo = () => {
return test.message();
}
ãããã§ã¯ãããŸããããåäœããã¯ãã§ãã
@nickofthyme ããªãã·ã§ã³1ã¯ããªããæã£ãŠããã®ã§æ£ããã§ãã ãã ããã³ãŒãã次ã®ããã«å€æŽãããšã次ã®ããã«ãªããŸãã
const foo = () => {}
export { foo }
ããããããã¯å£ããŸãã ãããããæ°ãããªããžã§ã¯ããªãã©ã«ãäœæããããããšã¯ã¹ããŒãããããã§ãã
èå³æ·±ã芳å¯ã ããããšã@maletor
Jestã®ããã¥ã¡ã³ãã«ã¯ãã¢ãžã¥ãŒã«ãéšåçã«ã¢ãã¯ããæ¹æ³ã®éåžžã«åçŽã§æ確ãªäŸããããŸãã ããã¯ãESimportã¹ããŒãã¡ã³ããšNoderequireã¹ããŒãã¡ã³ãã®äž¡æ¹ã§æ©èœããŸãã
https://jestjs.io/docs/en/jest-object#jestrequireactualmodulename
@johncmunsonããã¯è¯ãç¹ã§ãã ãã ããã¢ãžã¥ãŒã«ã®ã¢ãã¯ã瀺ãããã®äŸã¯ã jest.mock
_once_ãå®è¡ããå¿
èŠãããã ãã§ãã¢ãã¯ãããã¡ãœããã®ãããããã®ã¢ãžã¥ãŒã«ããã®å¥ã®ãšã¯ã¹ããŒãã䜿çšããªãå Žåã«ã®ã¿æ©èœããŸãã
äžèšã®äŸãèŠãŠãã ãã... foo
ãšbar
éã§ã¢ãžã¥ãŒã«ãç°ãªãæ¹æ³ã§ã¢ãã¯ããæ¹æ³ã瀺ãããã«ã bar
ãè¿œå ããŸããã
export const message = (): string => {
return 'Hello world';
}
export const foo = (): string => {
return message();
}
export const bar = (): (() => string) => {
return foo;
}
jest.mock
ãjest.requireActual
ãšäžç·ã«äœ¿çšãããšã次ã®ããã«ãªããšæããŸãã
import * as mockTestModule from './hello';
jest.mock('./hello');
const actualTestModule = jest.requireActual('./hello');
describe('test hello', function () {
afterAll(() => {
jest.restoreAllMocks();
});
// first test doesn't depend on any other method of the module so no mocks
it('should NOT mock message in foo', function () {
const actual = actualTestModule.foo();
expect(actual).toBe('Hello world');
});
// the second I want to mock message in foo
it('should mock message in foo', function () {
jest.spyOn(mockTestModule, 'message').mockReturnValue('my message');
const actual = actualTestModule.foo();
expect(actual).toBe('my message'); // fails
expect(mockTestModule.message).toHaveBeenCalledTimes(1); // never called
});
it('should mock foo in bar', function () {
jest.spyOn(mockTestModule, 'foo').mockReturnValue('my message');
const actual = actualTestModule.bar();
expect(actual()).toBe('my message'); // fails
expect(mockTestModule.message).toHaveBeenCalledTimes(1); // never called
});
});
jest.doMock
å¥ã
ã«ã¢ãã¯ããŠã¿ãŠããåãçµæãåŸãããŸããã
ã¯ãªãã¯ããŠã³ãŒãã衚瀺
`` `ts
import * as testModule from './ hello';
describeïŒ 'test hello'ãfunctionïŒïŒ{
afterAllïŒïŒïŒ=> {
jest.restoreAllMocksïŒïŒ;
}ïŒ;
it('should NOT mock message in foo', function () {
const actual = testModule.foo();
expect(actual).toBe('Hello world');
});
it('should mock message in foo', function () {
jest.doMock('./hello', () => {
// Require the original module to not be mocked...
const originalModule = jest.requireActual('./hello');
return {
...originalModule,
message: jest.fn().mockReturnValue('my message'),
};
});
const actual = testModule.foo();
expect(actual).toBe('my message'); // fails
expect(testModule.message).toHaveBeenCalledTimes(1); // never called
});
it('should mock foo in bar', function () {
jest.doMock('./hello', () => {
// Require the original module to not be mocked...
const originalModule = jest.requireActual('./hello');
return {
...originalModule,
foo: jest.fn().mockReturnValue('my message'),
};
});
const actual = testModule.bar()();
expect(actual).toBe('my message'); // fails
expect(testModule.foo).toHaveBeenCalledTimes(1); // never called
});
}ïŒ;
`` `
ãã®ã¢ãããŒãã®åé¡ã¯ãå®éã®ã¢ãžã¥ãŒã«ãèŠæ±ãã次ã«foo
ãåŒã³åºããšãã¢ãã¯ã§ã¯ãªãå®éã®message
é¢æ°ãåŒã³åºãããšã§ãã
ç§ã¯ãããããã»ã©åçŽã§ããããšãæã¿ãŸãããç§ãèŠããšãããããã¯ãã®ã¹ã¬ããã®äŸã«ã¯åœ¹ç«ã¡ãŸããã ããã§äœãã足ããªãå Žåã¯ãç¥ãããã ããã ç§ã¯åãã§éã¡ãèªããŸãã
解決çãæ¢ããŠããããã«åºãããã人ã«ãšã£ãŠã1ã€ã®ãã¡ã€ã«ã«å€ãã®const /é¢æ°ããšã¯ã¹ããŒãããç§ããã¹ãããŠãããã¡ã€ã«ã«ããããã€ã³ããŒããããšãã以äžã¯ç§ã®ããã«åããŠããããã§ã
function mockFunctions() { const original = require.requireActual('../myModule'); return { ...original, //Pass down all the exported objects test: jest.fn(() => {console.log('I didnt call the original')}), someFnIWantToCurry: {console.log('I will curry the original') return jest.fn((...args) => original.someFnIWantToCurry(...args)}), } jest.mock('../myModule', () => mockFunctions()); const storage = require.requireMock('../myModule'); `
以äžã¯æ©èœããå°ãçãã§ãïŒ
const module = require('./module');
jest.spyOn(module, 'myFn').mockImplementation(() => 'val');
掻åäœã§ãã¡ããã©import
ã®ä»£ããã«require
ïŒ
import * as module from './module';
ããã«ã¯ãå ã®æ©èœãç°¡åã«åŸ©å ããã¢ãã¯ãã¯ãªã¢ã§ãããšããå©ç¹ããããŸãã
解決çãæ¢ããŠããããã«åºãããã人ã«ãšã£ãŠã1ã€ã®ãã¡ã€ã«ã«å€ãã®const /é¢æ°ããšã¯ã¹ããŒãããç§ããã¹ãããŠãããã¡ã€ã«ã«ããããã€ã³ããŒããããšãã以äžã¯ç§ã®ããã«åããŠããããã§ã
function mockFunctions() { const original = require.requireActual('../myModule'); return { ...original, //Pass down all the exported objects test: jest.fn(() => {console.log('I didnt call the original')}), someFnIWantToCurry: {console.log('I will curry the original') return jest.fn((...args) => original.someFnIWantToCurry(...args)}), } jest.mock('../myModule', () => mockFunctions()); const storage = require.requireMock('../myModule'); `
以äžã¯æ©èœããå°ãçãã§ãïŒ
const module = require('./module'); jest.spyOn(module, 'myFn').mockImplementation(() => 'val');
掻åäœã§ãã¡ããã©
import
ã®ä»£ããã«require
ïŒimport * as module from './module';
ããã«ã¯ãå ã®æ©èœãç°¡åã«åŸ©å ããã¢ãã¯ãã¯ãªã¢ã§ãããšããå©ç¹ããããŸãã
ããã§ãããªããžã§ã¯ãã«getter
ããå®çŸ©ãããŠããªãå Žåãããã®ã¡ãœããã¯æ©èœããŸããã ãšã©ãŒã¡ãã»ãŒãžã¯æ¬¡ã®ããã«ãªããŸãã
Test suite failed to run
TypeError: Cannot set property useContent of #<Object> which has only a getter
ãã®å Žåãããããjest.mock(..)
ã䜿çšããå¿
èŠããããŸãã ïŒbowing_manïŒ
ç§ã®ã¢ãã¯ã¯ä»¥äžã䜿çšããŠåäœããŠããŸãã
import { unsubscribe } from "../lib/my-lib"
import { MyComponent } from "./index"
test("unsubscribe gets called", () => {
const module = require("../lib/my-lib")
jest.spyOn(
module,
"unsubscribe"
).mockImplementation(() => jest.fn())
const { getByTestId } = render(() => <MyComponent />)
let button = getByTestId("trigger.some.action.button")
fireEvent.press(button)
expect(unsubscribe).toHaveBeenCalled()
})
ããã»ã©ãšã¬ã¬ã³ãã«èŠãããç°¡åã«æ¡åŒµã§ããªãã®ã§ãéåžžã«ããŸãæ©èœããä»ã®ãšããç§ã®å Žåã«é©ããŠããŸãããããã誰ããä»ã®çŽ æŽãããæ§æãææ¡ã§ãããªãïŒ ããã¯ãæ©èœããŠããããã«èŠããå¯äžã®æ§æã§ãã
es6ã¢ãžã¥ãŒã«ã³ãŒãïŒ
export const funcA = () => {};
export const funcB = () => {
funcA();
};
CommonJSã«ãã©ã³ã¹ãã€ã«ããåŸïŒ
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.funcB = exports.funcA = void 0;
var funcA = function funcA() {};
exports.funcA = funcA; // You can mock or add a spy on this `funcA`
var funcB = function funcB() {
funcA(); // This is still original `funcA`
};
exports.funcB = funcB;
ãã®ç¶æ³ã解決ããæ¹æ³ã¯ãããããããŸãã
funcA
䜿çšã§ããããã«ããã®ããã«ã³ãŒããå€æŽããå¿
èŠããããŸãfunction funcA() {}
exports.funcA = funcA;
function funcB() {
exports.funcA(); // Now, this `exports.funcA` is added a spy or mocked. Keep the same reference to `funcA`
}
exports.funcB = funcB;
ãŸãã¯ã
export let funcA = () => {};
export const funcB = () => {
exports.funcA();
};
ãŠããããã¹ãã®çµæïŒ
PASS myModule.test.ts (9.225s)
funcB
â should call funcA (3ms)
-------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
myModule.ts | 100 | 100 | 100 | 100 |
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.967s
funcA
ãã¢ãã¯ããŸãããã«ã次ã®ããã¥ã¡ã³ãã確èªããå¿
èŠããããŸãïŒ https ïŒ require
ãæ£ç¢ºã«äœããããã確èªãã
ãã®stackoverflowã®æçš¿ã®è§£æ±ºçã¯ç§ã®ããã«åãã
https://stackoverflow.com/a/53402206/1217998
åºæ¬çã«æåã«ãå€æããããã¹ãŠã®é¢æ°ãjest.fn
ã«å€æããŸã
jest.mock('../../utils', () => {
const actualUtils = jest.requireActual('../../utils');
const originalImplementation = actualUtils.someFun;
return {
...actualUtils,
someFun: jest.fn()
.mockImplementation(originalImplementation),
};
});
const utils = require('../../utils');
ãã®åŸãå¿ èŠã«å¿ããŠéåžžã®ããã«äœ¿çšãããããã®ããã«ã¢ãã¯ãããã§ããŸã
jest.spyOn(utils, 'someFun').mockReturnValueOnce(true);
ããã䜿çšããŠãå ã®å®è£ ãååŸã§ããŸã
beforeEach(() => {
jest.clearAllMocks();
});
ãã®stackoverflowã®æçš¿ã®è§£æ±ºçã¯ç§ã®ããã«åãã
https://stackoverflow.com/a/53402206/1217998åºæ¬çã«æåã«ãå€æããããã¹ãŠã®é¢æ°ã
jest.fn
ã«å€æããŸãjest.mock('../../utils', () => { const actualUtils = jest.requireActual('../../utils'); const originalImplementation = actualUtils.someFun; return { ...actualUtils, someFun: jest.fn() .mockImplementation(originalImplementation), }; }); const utils = require('../../utils');
ãã®åŸãå¿ èŠã«å¿ããŠéåžžã®ããã«äœ¿çšãããããã®ããã«ã¢ãã¯ãããã§ããŸã
jest.spyOn(utils, 'someFun').mockReturnValueOnce(true);
ããã䜿çšããŠãå ã®å®è£ ãååŸã§ããŸã
beforeEach(() => { jest.clearAllMocks(); });
ããããšãããããŸããïŒ
Jestã®ããã¥ã¡ã³ãã«ã¯ãã¢ãžã¥ãŒã«ãéšåçã«ã¢ãã¯ããæ¹æ³ã®éåžžã«åçŽã§æ確ãªäŸããããŸãã ããã¯ãESimportã¹ããŒãã¡ã³ããšNoderequireã¹ããŒãã¡ã³ãã®äž¡æ¹ã§æ©èœããŸãã
https://jestjs.io/docs/en/jest-object#jestrequireactualmodulename
ã¢ãžã¥ãŒã«å ããã¢ãã¯é¢æ°ãåŒã³åºããå Žåã¯åäœããŸããã
ãŸããå ã®é¢æ°ãå€æŽããã«ãããã€ãã®ã«ã¹ã¿ã ïŒè¿œå ïŒå€æ°ã䜿çšããŠé¢æ°ãåŒã³åºãæ¹æ³ã§é¢æ°ãã¢ãã¯ããããšã圹ç«ã€å ŽåãããããšãããããŸããã
jest.mock('./someModule', () => {
const moduleMock = require.requireActual('./someModule');
return {
...moduleMock,
// will mock this function
someFunction: (args) =>
moduleMock.someFunction({
...args,
customArgument,
}),
};
});
ç§ã®å Žåãé¢æ°ã«come configãæž¡ãå¿ èŠããããŸãããããããªããšãããã©ã«ãã®ãã®ã䜿çšãããŸãã
ãããç§ããããè¡ãããã«èŠã€ããå¯äžã®æ¹æ³ãªã®ã§ãããªããããè¯ããŸãã¯ããç°¡åãªã¢ã€ãã¢ãæãã€ããå Žåã¯ãèããŠåãã§ããŸã:)
FWIW https://github.com/magicmark/jest-how-do-i-mock-x/blob/master/src/function-in-same-module/READMEã§ãå®è¡å¯èœãªäŸã䜿çšããŠããŸããŸãªã¢ãããŒãããŸãšããŸãã
ããã¯OPã®è³ªå/åé¡ã«ã¯çããŸãããããªãã¡ã¯ã¿ãªã³ã°ã䌎ã解決çã§ãã é¢æ°ãç°ãªããã¡ã€ã«ã«åå²ãããããã®ã€ã³ããŒããã¢ãã¯ããã®ãæãç°¡åãªæ¹æ³ã§ããããšãããããŸããã
// package.json
...
"scripts": {
"test": "jest",
...
"devDependencies": {
"@babel/preset-env": "^7.11.5",
"jest": "^24.9.0",
...
`` `js
// babel.config.js
module.exports = {
ããªã»ããïŒ[
[
'@ babel / preset-env'ã
{{
ã¿ãŒã²ããïŒ{
ããŒãïŒ 'çŸåš'ã
}ã
}ã
]ã
]ã
};
```js
// module-utils.js
export const isBabaYaga = () => {
return false
}
// module.js
import { isBabaYaga } from './module-utils'
export const isJohnWickBabaYaga = () => {
return isBabaYaga()
}
// modules.test.js
import { isJohnWickBabaYaga } from './module';
jest.mock('./module-utils', () => ({
isBabaYaga: jest.fn(() => true)
}))
test('John Wick is the Baba Yaga', () => {
// when
const isBabaYaga = isJohnWickBabaYaga()
// then
expect(isBabaYaga).toBeTruthy()
});
PASS src/module.test.js
â John Wick is the Baba Yaga (4ms)
æè¿ããã®åé¡ãçºçããŸããã ã³ãŒããå€æŽã§ããªããããææ¡ããããœãªã¥ãŒã·ã§ã³ã¯ã©ããæ©èœããŸããã babel-plugin-rewireãç§ã«ã¯æ©èœããŸããã é¢æ°ãåãã¢ãžã¥ãŒã«å ã®å¥ã®é¢æ°ã«ãã£ãŠåŒã³åºãããããšããã¹ãããããã®ä»ã®è§£æ±ºçã¯ãããŸããïŒ ããã¯æ£çŽã«èšããšãããŸããããããããè¡ãbabelãã©ã°ã€ã³ãããã¯ãã§ãã ã©ããªå©ãã§ã倧æè¿ã§ãïŒ
æè¿ããã®åé¡ãçºçããŸããã ã³ãŒããå€æŽã§ããªããããææ¡ããããœãªã¥ãŒã·ã§ã³ã¯ã©ããæ©èœããŸããã babel-plugin-rewireãç§ã«ã¯æ©èœããŸããã é¢æ°ãåãã¢ãžã¥ãŒã«å ã®å¥ã®é¢æ°ã«ãã£ãŠåŒã³åºãããããšããã¹ãããããã®ä»ã®è§£æ±ºçã¯ãããŸããïŒ ããã¯æ£çŽã«èšããšãããŸããããããããè¡ãbabelãã©ã°ã€ã³ãããã¯ãã§ãã ã©ããªå©ãã§ã倧æè¿ã§ãïŒ
https://github.com/facebook/jest/issues/936#issuecomment -659597840ããã§ãã¯ã¢ãŠãããŸãããïŒ ããã«ã¯ãã¢ãã¯é¢æ°ãåããã¡ã€ã«ã§åŒã³åºãæå°éã®åçŸããããŸãã
æãåèã«ãªãã³ã¡ã³ã
ã§ãããïŒ
http://facebook.github.io/jest/docs/api.html#mock-functionsãåç §ããŠ