ʹÓÃJest½øÐÐReactµ¥Ôª²âÊÔ
ÉÏһƪ / ÏÂһƪ 2019-03-08 09:35:21 / ¸öÈË·ÖÀࣺÈí¼þ²âÊÔ
¡¡¡¡Ç°ÖÃ֪ʶ
¡¡¡¡ÎªÊ²Ã´Òª½øÐвâÊÔ
¡¡¡¡1.²âÊÔ¿ÉÒÔÈ·±£µÃµ½Ô¤ÆڵĽá¹û
¡¡¡¡2.×÷ΪÏÖÓдúÂëÐÐΪµÄÃèÊö
¡¡¡¡3.´Ùʹ¿ª·¢Õßд¿É²âÊԵĴúÂ룬һ°ã¿É²âÊԵĴúÂë¿É¶ÁÐÔÒ²»á¸ßÒ»µã
¡¡¡¡4.Èç¹ûÒÀÀµµÄ×é¼þÓÐÐ޸ģ¬ÊÜÓ°ÏìµÄ×é¼þÄÜÔÚ²âÊÔÖз¢ÏÖ´íÎó
¡¡¡¡²âÊÔÀàÐÍ
¡¡¡¡µ¥Ôª²âÊÔ£ºÖ¸µÄÊÇÒÔÔ¼þµÄµ¥ÔªÎªµ¥Î»£¬¶ÔÈí¼þ½øÐвâÊÔ¡£µ¥Ôª¿ÉÒÔÊÇÒ»¸öº¯Êý£¬Ò²¿ÉÒÔÊÇÒ»¸öÄ£¿é»òÒ»¸ö×é¼þ£¬»ù±¾ÌØÕ÷¾ÍÊÇÖ»ÒªÊäÈë²»±ä£¬±Ø¶¨·µ»ØͬÑùµÄÊä³ö¡£Ò»¸öÈí¼þÔ½ÈÝÒ×Щµ¥Ôª²âÊÔ£¬¾Í±íÃ÷ËüµÄÄ£¿é»¯½á¹¹Ô½ºÃ£¬¸øÄ£¿éÖ®¼äµÄñîºÏÔ½Èõ¡£ReactµÄ×é¼þ»¯ºÍº¯Êýʽ±à³Ì£¬ÌìÉúÊʺϽøÐе¥Ôª²âÊÔ
¡¡¡¡¹¦ÄܲâÊÔ£ºÏ൱ÓÚÊǺںвâÊÔ£¬²âÊÔÕß²»Á˽â³ÌÐòµÄÄÚ²¿Çé¿ö£¬²»ÐèÒª¾ß±¸±à³ÌÓïÑÔµÄרÃÅ֪ʶ£¬Ö»ÖªµÀ³ÌÐòµÄÊäÈë¡¢Êä³öºÍ¹¦ÄÜ£¬´ÓÓû§µÄ½Ç¶ÈÕë¶ÔÈí¼þ½çÃæ¡¢¹¦ÄܺÍÍⲿ½á¹¹½øÐвâÊÔ£¬²»¿¼ÂÇÄÚ²¿µÄÂß¼
¡¡¡¡¼¯³É²âÊÔ£ºÔÚµ¥Ôª²âÊԵĻù´¡ÉÏ£¬½«ËùÓÐÄ£¿é°´ÕÕÉè¼ÆÒªÇó×é×°³É×Óϵͳ»òÕßϵͳ£¬½øÐвâÊÔ
¡¡¡¡Ã°Ñ̲âÊÔ£ºÔÚÕýʽȫÃæµÄ²âÊÔ֮ǰ£¬¶ÔÖ÷Òª¹¦ÄܽøÐеÄÓë²âÊÔ£¬È·ÈÏÖ÷Òª¹¦ÄÜÊÇ·ñÂú×ãÐèÒª£¬Èí¼þÊÇ·ñÄÜÕý³£ÔËÐÐ
¡¡¡¡¿ª·¢Ä£Ê½
¡¡¡¡TDD: ²âÊÔÇý¶¯¿ª·¢£¬Ó¢ÎÄΪTesting Driven Development£¬Ç¿µ÷µÄÊÇÒ»ÖÖ¿ª·¢·½Ê½£¬ÒÔ²âÊÔÀ´Çý¶¯Õû¸öÏîÄ¿£¬¼´Ïȸù¾Ý½Ó¿ÚÍê³É²âÊÔ±àд£¬È»ºóÔÚÍê³É¹¦ÄÜÊÇÒª²»¶Ïͨ¹ý²âÊÔ£¬×îÖÕÄ¿µÄÊÇͨ¹ýËùÓвâÊÔ
¡¡¡¡BDD: ÐÐΪÇý¶¯²âÊÔ£¬Ó¢ÎÄΪBehavior. Driven Development£¬Ç¿µ÷µÄÊÇд²âÊԵķç¸ñ£¬¼´²âÊÔҪдµÄÏñ×ÔÈ»ÓïÑÔ£¬ÈÃÏîÄ¿µÄ¸÷¸ö³ÉÔ±ÉõÖÁ²úÆ·¶¼ÄÜ¿´¶®²âÊÔ£¬ÉõÖÁ±àд²âÊÔ
¡¡¡¡TDDºÍBDDÓи÷×ÔµÄʹÓó¡¾°£¬BDDÒ»°ãÆ«ÏòÓÚϵͳ¹¦ÄܺÍÒµÎñÂß¼µÄ×Ô¶¯»¯²âÊÔÉè¼Æ£»¶øTDDÔÚ¿ìËÙ¿ª·¢²¢²âÊÔ¹¦ÄÜÄ£¿éµÄ¹ý³ÌÖÐÔò¸ü¼Ó¸ßЧ£¬ÒÔ¿ìËÙÍê³É¿ª·¢ÎªÄ¿µÄ¡£
¡¡¡¡Jest
¡¡¡¡JestÊÇFacebook¿ªÔ´µÄÒ»¸öÇ°¶Ë²âÊÔ¿ò¼Ü£¬Ö÷ÒªÓÃÓÚReactºÍReact NativeµÄµ¥Ôª²âÊÔ£¬Òѱ»¼¯³ÉÔÚcreate-react-appÖС£JestÌص㣺
¡¡¡¡1.Ò×ÓÃÐÔ£º»ùÓÚJasmine£¬Ìṩ¶ÏÑԿ⣬֧³Ö¶àÖÖ²âÊÔ·ç¸ñ
¡¡¡¡2.ÊÊÓ¦ÐÔ£ºJestÊÇÄ£¿é»¯¡¢¿ÉÀ©Õ¹ºÍ¿ÉÅäÖõÄ
¡¡¡¡4.¿ìÕÕ²âÊÔ£ºJestÄܹ»¶ÔReact×é¼þÊ÷½øÐÐÐòÁл¯£¬Éú³É¶ÔÓ¦µÄ×Ö·û´®¿ìÕÕ£¬Í¨¹ý±È½Ï×Ö·û´®Ìṩ¸ßÐÔÄܵÄUI¼ì²â
¡¡¡¡5.Mockϵͳ£ºJestʵÏÖÁËÒ»¸öÇ¿´óµÄMockϵͳ£¬Ö§³Ö×Ô¶¯ºÍÊÖ¶¯mock
¡¡¡¡6.Ö§³ÖÒì²½´úÂë²âÊÔ£ºÖ§³ÖPromiseºÍasync/await
¡¡¡¡×Ô¶¯Éú³É¾²Ì¬·ÖÎö½á¹û£ºÄÚÖÃIstanbul£¬²âÊÔ´úÂ븲¸ÇÂÊ£¬²¢Éú³É¶ÔÓ¦µÄ±¨¸æ
¡¡¡¡Enzyme
¡¡¡¡EnzymeÊÇAirbnb¿ªÔ´µÄReact²âÊÔ¹¤¾ß¿â¿â£¬Ëü¹¦Äܹý¶Ô¹Ù·½µÄ²âÊÔ¹¤¾ß¿âReactTestUtilsµÄ¶þ´Î·â×°£¬ÌṩÁËÒ»Ì×¼ò½àÇ¿´óµÄ API£¬²¢ÄÚÖÃCheerio£¬
¡¡¡¡ÊµÏÖÁËjQuery·ç¸ñµÄ·½Ê½½øÐÐDOM ´¦Àí£¬¿ª·¢ÌåÑéÊ®·ÖÓѺá£ÔÚ¿ªÔ´ÉçÇøÓг¬¸ßÈËÆø£¬Í¬Ê±Ò²»ñµÃÁËReact ¹Ù·½µÄÍƼö¡£
¡¡¡¡²âÊÔ»·¾³´î½¨
¡¡¡¡°²×°Jest¡¢Enzyme£¬ÒÔ¼°babel-jest¡£Èç¹ûReactµÄ°æ±¾ÊÇ15»òÕß16£¬ÐèÒª°²×°¶ÔÓ¦µÄenzyme-adapter-react-15ºÍenzyme-adapter-react-16²¢ÅäÖá£
import Enzyme from 'enzyme'; ¡¡¡¡import Adapter from 'enzyme-adapter-react-16'; ¡¡¡¡Enzyme.configure({ adapter: new Adapter() }); |
¡¡¡¡ÔÚpackage.jsonÖеÄscriptÖÐÔö¼Ó"test: jest --config .jest.js"
.jest.jsÎļþ ¡¡¡¡module.exports = { ¡¡¡¡setupFiles: [ ¡¡¡¡'./test/setup.js', ¡¡¡¡], ¡¡¡¡moduleFileExtensions: [ ¡¡¡¡'js', ¡¡¡¡'jsx', ¡¡¡¡], ¡¡¡¡testPathIgnorePatterns: [ ¡¡¡¡'/node_modules/', ¡¡¡¡], ¡¡¡¡testRegex: '.*\\.test\\.js$', ¡¡¡¡collectCoverage: false, ¡¡¡¡collectCoverageFrom: [ ¡¡¡¡'src/components/**/*.{js}', ¡¡¡¡], ¡¡¡¡moduleNameMapper: { ¡¡¡¡"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js", ¡¡¡¡"\\.(css|less|scss)$": "<rootDir>/__mocks__/styleMock.js" ¡¡¡¡}, ¡¡¡¡transform. { ¡¡¡¡"^.+\\.js$": "babel-jest" ¡¡¡¡}, ¡¡¡¡}; |
¡¡¡¡setupFiles£ºÅäÖÃÎļþ£¬ÔÚÔËÐвâÊÔ°¸Àý´úÂë֮ǰ£¬Jest»áÏÈÔËÐÐÕâÀïµÄÅäÖÃÎļþÀ´³õʼ»¯Ö¸¶¨µÄ²âÊÔ»·¾³
¡¡¡¡moduleFileExtensions£º´ú±íÖ§³Ö¼ÓÔصÄÎļþÃû
¡¡¡¡testPathIgnorePatterns£ºÓÃÕýÔòÀ´Æ¥Åä²»ÓòâÊÔµÄÎļþ
¡¡¡¡testRegex£ºÕýÔò±íʾµÄ²âÊÔÎļþ£¬²âÊÔÎļþµÄ¸ñʽΪxxx.test.js
¡¡¡¡collectCoverage£ºÊÇ·ñÉú³É²âÊÔ¸²¸Ç±¨¸æ£¬Èç¹û¿ªÆô£¬»áÔö¼Ó²âÊÔµÄʱ¼ä
¡¡¡¡collectCoverageFrom£ºÉú³É²âÊÔ¸²¸Ç±¨¸æÊǼì²âµÄ¸²¸ÇÎļþ
¡¡¡¡moduleNameMapper£º´ú±íÐèÒª±»MockµÄ×ÊÔ´Ãû³Æ
¡¡¡¡transform£ºÓÃbabel-jestÀ´±àÒëÎļþ£¬Éú³ÉES6/7µÄÓï·¨
¡¡¡¡Jest
¡¡¡¡globals API
¡¡¡¡it(name, fn, timeout)£º±ðÃûtest£¬ÓÃÀ´·Å²âÊÔÓÃÀý
¡¡¡¡afterAll(fn, timeout)£ºËùÓвâÊÔÓÃÀýÅÜÍêÒÔºóÖ´Ðеķ½·¨
¡¡¡¡beforeAll(fn, timeout)£ºËùÓвâÊÔÓÃÀýÖ´ÐÐ֮ǰִÐеķ½·¨
¡¡¡¡afterEach(fn)£ºÔÚÿ¸ö²âÊÔÓÃÀýÖ´ÐÐÍêºóÖ´Ðеķ½·¨
¡¡¡¡beforeEach(fn)£ºÔÚÿ¸ö²âÊÔÓÃÀýÖ´ÐÐ֮ǰÐèÒªÖ´Ðеķ½·¨
¡¡¡¡È«¾ÖºÍdescribe¶¼¿ÉÒÔÓÐÉÏÃæËĸöÖÜÆÚº¯Êý£¬describeµÄafterº¯ÊýÓÅÏȼ¶Òª¸ßÓÚÈ«¾ÖµÄafterº¯Êý£¬describeµÄbeforeº¯ÊýÓÅÏȼ¶ÒªµÍÓÚÈ«¾ÖµÄbeforeº¯Êý
¡¡ beforeAll(() => { ¡¡¡¡console.log('global before all'); ¡¡¡¡}); ¡¡¡¡afterAll(() => { ¡¡¡¡console.log('global after all'); ¡¡¡¡}); ¡¡¡¡beforeEach(() =>{ ¡¡¡¡console.log('global before each'); ¡¡¡¡}); ¡¡¡¡afterEach(() => { ¡¡¡¡console.log('global after each'); ¡¡¡¡}); ¡¡¡¡describe('test1', () => { ¡¡¡¡beforeAll(() => { ¡¡¡¡console.log('test1 before all'); ¡¡¡¡}); ¡¡¡¡afterAll(() => { ¡¡¡¡console.log('test1 after all'); ¡¡¡¡}); ¡¡¡¡beforeEach(() => { ¡¡¡¡console.log('test1 before each'); ¡¡¡¡}); ¡¡¡¡afterEach(() => { ¡¡¡¡console.log('test1 after each'); ¡¡¡¡}); ¡¡¡¡it('test sum', () => { ¡¡¡¡expect(sum(2, 3)).toEqual(5); ¡¡¡¡}); ¡¡¡¡it('test mutil', () => { ¡¡¡¡expect(sum(2, 3)).toEqual(7); ¡¡¡¡}); ¡¡¡¡}); |
¡¡
¡¡¡¡config
¡¡¡¡JestÓµÓзḻµÄÅäÖÃÏ¿ÉÒÔдÔÚpackage.jsonÀïÔö¼ÓÔö¼Ójest×Ö¶ÎÀ´½øÐÐÅäÖ㬻òÕßͨ¹ýÃüÁîÐÐ--configÀ´Ö¸¶¨ÅäÖÃÎļþ¡£
¡¡¡¡jest¶ÔÏó
¡¡¡¡jest.fn(implementation)£º·µ»ØÒ»¸öÈ«ÐÂûÓÐʹÓùýµÄmock function£¬Õâ¸öfunctionÔÚ±»µ÷ÓõÄʱºò»á¼Ç¼ºÜ¶àºÍº¯Êýµ÷ÓÃÓйصÄÐÅÏ¢
¡¡¡¡jest.mock(moduleName, factory, options)£ºÓÃÀ´mockһЩģ¿é»òÕßÎļþ
¡¡¡¡jest.spyOn(object, methodName)£º·µ»ØÒ»¸ömock function£¬ºÍjest.fnÏàËÆ£¬µ«ÊÇÄܹ»×·×Ùobject[methodName]µÄµ÷ÓÃÐÅÏ¢£¬ÀàËÆSinon
¡¡¡¡Mock Functions
¡¡¡¡Ê¹ÓÃmockº¯Êý¿ÉÒÔÇáËɵÄÄ£Äâ´úÂëÖ®¼äµÄÒÀÀµ£¬¿ÉÒÔͨ¹ýfn»òspyOnÀ´mockij¸ö¾ßÌåµÄº¯Êý£»Í¨¹ýmockÀ´Ä£Äâij¸öÄ£¿é¡£¾ßÌåµÄAPI¿ÉÒÔ¿´mock-function-api¡£
¡¡¡¡¿ìÕÕ
¡¡¡¡¿ìÕÕ»áÉú³ÉÒ»¸ö×é¼þµÄUI½á¹¹£¬²¢ÓÃ×Ö·û´®µÄÐÎʽ´æ·ÅÔÚ__snapshots__ÎļþÀͨ¹ý±È½ÏÁ½¸ö×Ö·û´®À´ÅжÏUIÊÇ·ñ¸Ä±ä£¬ÒòΪÊÇ×Ö·û´®±È½Ï£¬ËùÒÔÐÔÄܸܺߡ£
¡¡¡¡ÒªÊ¹ÓÿìÕÕ¹¦ÄÜ£¬ÐèÒªÒýÈëreact-test-renderer¿â£¬Ê¹ÓÃÆäÖеÄrenderer·½·¨£¬jestÔÚÖ´ÐеÄʱºòÈç¹û·¢ÏÖtoMatchSnapshot·½·¨£¬»áÔÚͬ¼¶Ä¿Â¼ÏÂÉú³ÉÒ»¸ö__snapshotsÎļþ¼ÐÓÃÀ´´æ·Å¿ìÕÕÎļþ£¬ÒÔºóÿ´Î²âÊÔµÄʱºò¶¼»áºÍµÚÒ»´ÎÉú³ÉµÄ¿ìÕÕ½øÐбȽϡ£¿ÉÒÔʹÓÃjest --updateSnapshotÀ´¸üпìÕÕÎļþ¡£
¡¡¡¡Òì²½²âÊÔ
¡¡¡¡JestÖ§³Ö¶ÔÒì²½µÄ²âÊÔ£¬Ö§³ÖPromiseºÍAsync/AwaitÁ½ÖÖ·½Ê½µÄÒì²½²âÊÔ¡£
¡¡¡¡³£¼û¶ÏÑÔ
¡¡¡¡expect(value)£ºÒª²âÊÔÒ»¸öÖµ½øÐжÏÑÔµÄʱºò£¬ÒªÊ¹ÓÃexpect¶ÔÖµ½øÐаü¹ü
¡¡¡¡toBe(value)£ºÊ¹ÓÃObject.isÀ´½øÐбȽϣ¬Èç¹û½øÐи¡µãÊýµÄ±È½Ï£¬ÒªÊ¹ÓÃtoBeCloseTo
¡¡¡¡not£ºÓÃÀ´È¡·´
¡¡¡¡toEqual(value)£ºÓÃÓÚ¶ÔÏóµÄÉî±È½Ï
¡¡¡¡toMatch(regexpOrString)£ºÓÃÀ´¼ì²é×Ö·û´®ÊÇ·ñÆ¥Å䣬¿ÉÒÔÊÇÕýÔò±í´ïʽ»òÕß×Ö·û´®
¡¡¡¡toContain(item)£ºÓÃÀ´ÅжÏitemÊÇ·ñÔÚÒ»¸öÊý×éÖУ¬Ò²¿ÉÒÔÓÃÓÚ×Ö·û´®µÄÅжÏ
¡¡¡¡toBeNull(value)£ºÖ»Æ¥Åänull
¡¡¡¡toBeUndefined(value)£ºÖ»Æ¥Åäundefined
¡¡¡¡toBeDefined(value)£ºÓëtoBeUndefinedÏà·´
¡¡¡¡toBeTruthy(value)£ºÆ¥ÅäÈκÎʹifÓï¾äΪÕæµÄÖµ
¡¡¡¡toBeFalsy(value)£ºÆ¥ÅäÈκÎʹifÓï¾äΪ¼ÙµÄÖµ
¡¡¡¡toBeGreaterThan(number)£º ´óÓÚ
¡¡¡¡toBeGreaterThanOrEqual(number)£º´óÓÚµÈÓÚ
¡¡¡¡toBeLessThan(number)£ºÐ¡ÓÚ
¡¡¡¡toBeLessThanOrEqual(number)£ºÐ¡ÓÚµÈÓÚ
¡¡¡¡toBeInstanceOf(class)£ºÅжÏÊDz»ÊÇclassµÄʵÀý
¡¡¡¡anything(value)£ºÆ¥Åä³ýÁËnullºÍundefinedÒÔÍâµÄËùÓÐÖµ
¡¡¡¡resolves£ºÓÃÀ´È¡³öpromiseΪfulfilledʱ°ü¹üµÄÖµ£¬Ö§³ÖÁ´Ê½µ÷ÓÃ
¡¡¡¡rejects£ºÓÃÀ´È¡³öpromiseΪrejectedʱ°ü¹üµÄÖµ£¬Ö§³ÖÁ´Ê½µ÷ÓÃ
¡¡¡¡toHaveBeenCalled()£ºÓÃÀ´ÅжÏmock functionÊÇ·ñ±»µ÷Óùý
¡¡¡¡toHaveBeenCalledTimes(number)£ºÓÃÀ´ÅжÏmock function±»µ÷ÓõĴÎÊý
¡¡¡¡assertions(number)£ºÑéÖ¤ÔÚÒ»¸ö²âÊÔÓÃÀýÖÐÓÐnumber¸ö¶ÏÑÔ±»µ÷ÓÃ
¡¡¡¡extend(matchers)£º×Ô¶¨ÒåһЩ¶ÏÑÔ
¡¡¡¡Enzyme
¡¡¡¡ÈýÖÖäÖȾ·½·¨
¡¡¡¡shallow£ºÇ³äÖȾ£¬ÊǶԹٷ½µÄShallow RendererµÄ·â×°¡£½«×é¼þäÖȾ³ÉÐéÄâDOM¶ÔÏó£¬Ö»»áäÖȾµÚÒ»²ã£¬×Ó×é¼þ½«²»»á±»äÖȾ³öÀ´£¬Ê¹µÃЧÂʷdz£¸ß¡£²»ÐèÒªDOM»·¾³£¬ ²¢¿ÉÒÔʹÓÃjQueryµÄ·½Ê½·ÃÎÊ×é¼þµÄÐÅÏ¢
¡¡¡¡render£º¾²Ì¬äÖȾ£¬Ëü½«React×é¼þäÖȾ³É¾²Ì¬µÄHTML×Ö·û´®£¬È»ºóʹÓÃCheerioÕâ¸ö¿â½âÎöÕâ¶Î×Ö·û´®£¬²¢·µ»ØÒ»¸öCheerioµÄʵÀý¶ÔÏ󣬿ÉÒÔÓÃÀ´·ÖÎö×é¼þµÄhtml½á¹¹
¡¡¡¡mount£ºÍêÈ«äÖȾ£¬Ëü½«×é¼þäÖȾ¼ÓÔسÉÒ»¸öÕæʵµÄDOM½Úµã£¬ÓÃÀ´²âÊÔDOM APIµÄ½»»¥ºÍ×é¼þµÄÉúÃüÖÜÆÚ¡£Óõ½ÁËjsdomÀ´Ä£Äâä¯ÀÀÆ÷»·¾³
¡¡¡¡ÈýÖÖ·½·¨ÖУ¬shallowºÍmountÒòΪ·µ»ØµÄÊÇDOM¶ÔÏ󣬿ÉÒÔÓÃsimulate½øÐн»»¥Ä£Ä⣬¶ørender·½·¨²»¿ÉÒÔ¡£Ò»°ãshallow·½·¨¾Í¿ÉÒÔÂú×ãÐèÇó£¬Èç¹ûÐèÒª¶Ô×Ó×é¼þ½øÐÐÅжϣ¬ÐèҪʹÓÃrender£¬Èç¹ûÐèÒª²âÊÔ×é¼þµÄÉúÃüÖÜÆÚ£¬ÐèҪʹÓÃmount·½·¨¡£
¡¡¡¡³£Ó÷½·¨
¡¡¡¡simulate(event, mock)£ºÄ£Äâʼþ£¬ÓÃÀ´´¥·¢Ê¼þ£¬eventΪʼþÃû³Æ£¬mockΪһ¸öevent object
¡¡¡¡instance()£º·µ»Ø×é¼þµÄʵÀý
¡¡¡¡find(selector)£º¸ù¾ÝÑ¡ÔñÆ÷²éÕҽڵ㣬selector¿ÉÒÔÊÇCSSÖеÄÑ¡ÔñÆ÷£¬»òÕßÊÇ×é¼þµÄ¹¹Ô캯Êý£¬×é¼þµÄdisplay nameµÈ
¡¡¡¡at(index)£º·µ»ØÒ»¸öäÖȾ¹ýµÄ¶ÔÏó
¡¡¡¡get(index)£º·µ»ØÒ»¸öreact node£¬Òª²âÊÔËü£¬ÐèÒªÖØÐÂäÖȾ
¡¡¡¡contains(nodeOrNodes)£ºµ±Ç°¶ÔÏóÊÇ·ñ°üº¬²ÎÊýÖصã node£¬²ÎÊýÀàÐÍΪreact¶ÔÏó»ò¶ÔÏóÊý×é
¡¡¡¡text()£º·µ»Øµ±Ç°×é¼þµÄÎı¾ÄÚÈÝ
¡¡¡¡html()£º ·µ»Øµ±Ç°×é¼þµÄHTML´úÂëÐÎʽ
¡¡¡¡props()£º·µ»Ø¸ù×é¼þµÄËùÓÐÊôÐÔ
¡¡¡¡prop(key)£º·µ»Ø¸ù×é¼þµÄÖ¸¶¨ÊôÐÔ
¡¡¡¡state()£º·µ»Ø¸ù×é¼þµÄ״̬
¡¡¡¡setState(nextState)£ºÉèÖøù×é¼þµÄ״̬
¡¡¡¡setProps(nextProps)£ºÉèÖøù×é¼þµÄÊôÐÔ
¡¡¡¡±àд²âÊÔÓÃÀý
¡¡¡¡×é¼þ´úÂë
todo-list/index.js ¡¡¡¡import React, { Component } from 'react'; ¡¡¡¡import { Button } from 'antd'; ¡¡¡¡export default class TodoList extends Component { ¡¡¡¡constructor(props) { ¡¡¡¡super(props); ¡¡¡¡this.handleTest2 = this.handleTest2.bind(this); ¡¡¡¡} ¡¡¡¡handleTest = () => { ¡¡¡¡console.log('test'); ¡¡¡¡} ¡¡¡¡handleTest2() { ¡¡¡¡console.log('test2'); ¡¡¡¡} ¡¡¡¡componentDidMount() {} ¡¡¡¡render() { ¡¡¡¡return ( ¡¡¡¡<div className="todo-list"> ¡¡¡¡{this.props.list.map((todo, index) => (<div key={index}> ¡¡¡¡<span className="item-text ">{todo}</span> ¡¡¡¡<Button nClick={() => this.props.deleteTodo(index)} >done</Button> ¡¡¡¡</div>))} ¡¡¡¡</div> ¡¡¡¡); ¡¡¡¡} ¡¡¡¡} |
¡¡¡¡²âÊÔÎļþsetupÉèÖÃ
const props = { ¡¡¡¡list: ['first', 'second'], ¡¡¡¡deleteTodo: jest.fn(), ¡¡¡¡}; ¡¡¡¡const setup = () => { ¡¡¡¡const wrapper = shallow(<TodoList {...props} />); ¡¡¡¡return { ¡¡¡¡props, ¡¡¡¡wrapper, ¡¡¡¡}; ¡¡¡¡}; ¡¡¡¡const setupByRender = () => { ¡¡¡¡const wrapper = render(<TodoList {...props} />); ¡¡¡¡return { ¡¡¡¡props, ¡¡¡¡wrapper, ¡¡¡¡}; ¡¡¡¡}; ¡¡¡¡const setupByMount = () => { ¡¡¡¡const wrapper = mount(<TodoList {...props} />); ¡¡¡¡return { ¡¡¡¡props, ¡¡¡¡wrapper, ¡¡¡¡}; ¡¡¡¡}; |
¡¡¡¡Ê¹Óà snapshot ½øÐÐ UI ²âÊÔ
it('renders correctly', () => { ¡¡¡¡const tree = renderer ¡¡¡¡.create(<TodoList {...props} />) ¡¡¡¡.toJSON(); ¡¡¡¡expect(tree).toMatchSnapshot(); ¡¡¡¡}); |
¡¡¡¡µ±Ê¹ÓÃtoMatchSnapshotµÄʱºò£¬»áÉú³ÉÒ»·Ý×é¼þDOMµÄ¿ìÕÕ£¬ÒÔºóÿ´ÎÔËÐвâÊÔÓÃÀýµÄʱºò£¬¶¼»áÉú³ÉÒ»·Ý×é¼þ¿ìÕպ͵ÚÒ»´ÎÉú³ÉµÄ¿ìÕÕ½øÐжԱȣ¬Èç¹û¶Ô×é¼þµÄ½á¹¹½øÐÐÐ޸ģ¬ÄÇôÉú³ÉµÄ¿ìÕվͻá¶Ô±Èʧ°Ü¡£¿ÉÒÔͨ¹ý¸üпìÕÕÖØнøÐÐUI²âÊÔ¡£
¡¡¡¡¶Ô×é¼þ½Úµã½øÐвâÊÔ
it('should has Button', () => { ¡¡¡¡const { wrapper } = setup(); ¡¡¡¡expect(wrapper.find('Button').length).toBe(2); ¡¡¡¡}); ¡¡¡¡it('should render 2 item', () => { ¡¡¡¡const { wrapper } = setupByRender(); ¡¡¡¡expect(wrapper.find('button').length).toBe(2); ¡¡¡¡}); ¡¡¡¡it('should render item equal', () => { ¡¡¡¡const { wrapper } = setupByMount(); ¡¡¡¡wrapper.find('.item-text').forEach((node, index) => { ¡¡¡¡expect(node.text()).toBe(wrapper.props().list[index]) ¡¡¡¡}); ¡¡¡¡}); ¡¡¡¡it('click item to be done', () => { ¡¡¡¡const { wrapper } = setupByMount(); ¡¡¡¡wrapper.find('Button').at(0).simulate('click'); ¡¡¡¡expect(props.deleteTodo).toBeCalled(); ¡¡¡¡}); |
¡¡¡¡ÅжÏ×é¼þÊÇ·ñÓÐButtonÕâ¸ö×é¼þ£¬ÒòΪ²»ÐèÒªäÖȾ×ӽڵ㣬ËùÒÔʹÓÃshallow·½·¨½øÐÐ×é¼þµÄäÖȾ£¬ÒòΪpropsµÄlistÓÐÁ½ÏËùÒÔÔ¤ÆÚÓ¦¸ÃÓÐÁ½¸öButton×é¼þ¡£
¡¡¡¡ÅжÏ×é¼þÊÇ·ñÓÐbuttonÕâ¸öÔªËØ£¬ÒòΪbuttonÊÇButton×é¼þÀïµÄÔªËØ£¬ËùÓÐʹÓÃrender·½·¨½øÐÐäÖȾ£¬Ô¤ÆÚÒ²»áÕÒµ½Á¬¸öbuttonÔªËØ¡£
¡¡¡¡ÅжÏ×é¼þµÄÄÚÈÝ£¬Ê¹ÓÃmount·½·¨½øÐÐäÖȾ£¬È»ºóʹÓÃforEachÅжÏ.item-textµÄÄÚÈÝÊÇ·ñºÍ´«ÈëµÄÖµÏàµÈʹÓÃsimulateÀ´´¥·¢clickʼþ£¬ÒòΪdeleteTodo±»mockÁË£¬ËùÒÔ¿ÉÒÔÓÃdeleteTodo·½·¨Ê±ºò±»µ÷ÓÃÀ´ÅжÏclickʼþÊÇ·ñ±»´¥·¢¡£
¡¡¡¡²âÊÔ×é¼þÉúÃüÖÜÆÚ
//ʹÓÃspyÌæÉíµÄʱºò£¬ÔÚ²âÊÔÓÃÀý½áÊøºó£¬Òª¶Ôspy½øÐÐrestore£¬²»È»Õâ¸öspy»áÒ»Ö±´æÔÚ£¬²¢ÇÒÎÞ·¨¶ÔÏàͬµÄ·½·¨ÔٴνøÐÐspy¡£ ¡¡¡¡it('calls componentDidMount', () => { ¡¡¡¡const componentDidMountSpy = jest.spyOn(TodoList.prototype, 'componentDidMount'); ¡¡¡¡const { wrapper } = setup(); ¡¡¡¡expect(componentDidMountSpy).toHaveBeenCalled(); ¡¡¡¡componentDidMountSpy.mockRestore(); ¡¡¡¡}); |
¡¡¡¡Ê¹ÓÃspyOnÀ´mock ×é¼þµÄcomponentDidMount£¬ÌæÉíº¯ÊýÒªÔÚ×é¼þäÖȾ֮ǰ£¬ËùÓÐÌæÉíº¯ÊýÒª¶¨ÒåÔÚsetupÖ´ÐÐ֮ǰ£¬²¢ÇÒÔÚÅжÏÒÔºóÒª¶ÔÌæÉíº¯Êýrestore£¬²»È»Õâ¸öÌæÉíº¯Êý»áÒ»Ö±´æÔÚ£¬ÇÒ±»mockµÄÄǸöº¯ÊýÎÞ·¨±»ÔÙ´Îmock¡£
¡¡¡¡²âÊÔ×é¼þµÄÄÚ²¿º¯Êý
it('calls component handleTest', () => { // classÖÐʹÓüýÍ·º¯ÊýÀ´¶¨Òå·½·¨ ¡¡¡¡const { wrapper } = setup(); ¡¡¡¡const spyFunction = jest.spyOn(wrapper.instance(), 'handleTest'); ¡¡¡¡wrapper.instance().handleTest(); ¡¡¡¡expect(spyFunction).toHaveBeenCalled(); ¡¡¡¡spyFunction.mockRestore(); ¡¡¡¡}); ¡¡¡¡it('calls component handleTest2', () => { //ÔÚconstructorʹÓÃbindÀ´¶¨Òå·½·¨ ¡¡¡¡const spyFunction = jest.spyOn(TodoList.prototype, 'handleTest2'); ¡¡¡¡const { wrapper } = setup(); ¡¡¡¡wrapper.instance().handleTest2(); ¡¡¡¡expect(spyFunction).toHaveBeenCalled(); ¡¡¡¡spyFunction.mockRestore(); ¡¡¡¡}); |
¡¡ ʹÓÃinstanceº¯ÊýÀ´È¡µÃ×é¼þµÄʵÀý£¬²¢ÓÃspyOn·½·¨À´mockʵÀýÉϵÄÄÚ²¿·½·¨£¬È»ºóÓÃÕâ¸öʵÀýÈ¥µ÷ÓÃÄǸöÄÚ²¿·½·¨£¬¾Í¿ÉÒÔÓÃÌæÉíÀ´ÅжÏÕâ¸öÄÚ²¿º¯ÊýÊÇ·ñ±»µ÷Óá£Èç¹ûÄÚ²¿·½·¨ÊÇÓüýÍ·º¯ÊýÀ´¶¨ÒåµÄʱºò£¬ÐèÒª¶ÔʵÀý½øÐÐmock£»Èç¹ûÄÚ²¿·½·¨ÊÇͨ¹ýÕý³£µÄ·½Ê½»òÕßbindµÄ·½Ê½¶¨ÒåµÄ£¬ÄÇôÐèÒª¶Ô×é¼þµÄprototype½øÐÐmock¡£Æäʵ¶ÔÉúÃüÖÜÆÚ»òÕßÄÚ²¿º¯ÊýµÄ²âÊÔ£¬¿ÉÒÔͨ¹ýһЩstateµÄ¸Ä±ä½øÐÐÅжϣ¬ÒòΪÕâЩº¯ÊýµÄµ÷ÓÃÒ»°ã¶¼»á¶Ô×é¼þµÄstate½øÐÐһЩ²Ù×÷¡£
¡¡¡¡Manual Mocks
¡¡¡¡¶ÔÈ«¾ÖµÄÄ£¿é(moduleName)½øÐÐÊÖ¶¯Ä£Ä⣬ÐèÒªÔÚnode_modulesƽ¼¶µÄλÖÃн¨Ò»¸ö__mocks__Îļþ¼Ð£¬²¢ÔÚÎļþ¼ÐÖÐн¨Ò»¸ömoduleNameµÄÎļþ
¡¡¡¡¶Ôij¸öÎļþ(fileName)½øÐÐÊÖ¶¯Ä£Ä⣬ÐèÒªÔÚ±»Ä£ÄâµÄÎļþƽ¼¶µÄλÖÃн¨Ò»¸ö__mocks__Îļþ¼Ð£¬È»ºóÔÚÎļþ¼ÐÖÐн¨Ò»¸öfileNameµÄÎļþ
add/index.js ¡¡¡¡import { add } from 'lodash'; ¡¡¡¡import { multip } from '../../utils/index'; ¡¡¡¡export default function sum(a, b) { ¡¡¡¡return add(a, b); ¡¡¡¡} ¡¡¡¡export function m(a, b) { ¡¡¡¡return multip(a, b); ¡¡¡¡} |
¡¡
add/__test__/index.test.js ¡¡¡¡import sum, { m } from '../index'; ¡¡¡¡jest.mock('lodash'); ¡¡¡¡jest.mock('../../../utils/index'); ¡¡¡¡describe('test mocks', () => { ¡¡¡¡it('test sum', () => { ¡¡¡¡expect(sum(2, 3)).toEqual(5); ¡¡¡¡}); ¡¡¡¡it('test mutilp', () => { ¡¡¡¡expect(m(2, 3)).toEqual(7); ¡¡¡¡}); ¡¡¡¡}); |
¡¡ _mocks_:
¡¡¡¡ÔÚ²âÊÔÎļþÖÐʹÓÃmock()·½·¨¶ÔÒª½øÐÐmockµÄÎļþ½øÐÐÒýÓã¬Jest¾Í»á×Ô¶¯È¥Ñ°ÕÒ¶ÔÓ¦µÄ__mocks__ÖеÄÎļþ²¢½øÐÐÌæ»»£¬lodashÖеÄaddºÍutilsÖеÄmultip·½·¨¾Í»á±»mock³É¶ÔÓ¦µÄ·½·¨¡£¿ÉÒÔʹÓÃ×Ô¶¯´úÀíµÄ·½Ê½¶ÔÏîÄ¿µÄÒì²½×é¼þ¿â(fetch¡¢axios)½øÐÐmock£¬»òÕßʹÓÃfetch-mock¡¢jest-fetch-mockÀ´Ä£ÄâÒì²½ÇëÇó¡£
¡¡¡¡¶ÔÒì²½·½·¨½øÐвâÊÔ
async/index.js ¡¡¡¡import request from './request'; ¡¡¡¡export function getUserName(userID) { ¡¡¡¡return request(`/users/${userID}`).then(user => user.name); ¡¡¡¡} ¡¡¡¡async/request.js ¡¡¡¡const http = require('http'); ¡¡¡¡export default function request(url) { ¡¡¡¡return new Promise((resolve) => { ¡¡¡¡// This is an example of an http request, for example to fetch ¡¡¡¡// user data from an API. ¡¡¡¡// This module is being mocked in __mocks__/request.js ¡¡¡¡http.get({ path: url }, (response) => { ¡¡¡¡let data = ''; ¡¡¡¡response.on('data', _data => (data += _data)); ¡¡¡¡response.on('end', () => resolve(data)); ¡¡¡¡}); ¡¡¡¡}); ¡¡¡¡} |
¡¡¡¡mock request:
const users = { ¡¡¡¡4: { ¡¡¡¡name: 'hehe', ¡¡¡¡}, ¡¡¡¡5: { ¡¡¡¡name: 'haha', ¡¡¡¡}, ¡¡¡¡}; ¡¡¡¡export default function request(url) { ¡¡¡¡return new Promise((resolve, reject) => { ¡¡¡¡const userID = parseInt(url.substr('/users/'.length), 10); ¡¡¡¡process.nextTick(() => { ¡¡¡¡users[userID] ? ¡¡¡¡resolve(users[userID]) : ¡¡¡¡reject({ ¡¡¡¡error: `User with ${userID} not found.`, ¡¡¡¡}); ¡¡¡¡}); ¡¡¡¡}); ¡¡¡¡} |
¡¡¡¡request.js¿ÉÒÔ¿´³ÉÊÇÒ»¸öÓÃÓÚÇëÇóÊý¾ÝµÄÄ£¿é£¬ÊÖ¶¯mockÕâ¸öÄ£¿é£¬Ê¹Ëü·µ»ØÒ»¸öPromise¶ÔÏó£¬ÓÃÓÚ¶ÔÒì²½µÄ´¦Àí¡£
΢ÈíÑ
TAG: