Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
Angular µ¥Ôª²âÊÔ½²½â
 
  5980  次浏览      31
 2019-3-12
 
±à¼­ÍƼö:

±¾ÎÄÀ´×ÔÓÚcsdn£¬±¾ÎÄÖ÷Òª½éÉÜÁ˲âÊԵķÖÀ࣬ATDD,TDD,BDD,DDDµÄÇø±ðÒÔ¼°Karma¡¢jasmineµÈ¹¤¾ßµÄ½éÉܵÈÏà¹ØÄÚÈÝ¡£

Angular_µ¥Ôª²âÊÔ

²âÊÔ·ÖÀà

°´¿ª·¢½×¶Î»®·Ö

µ¥Ôª²âÊÔ

µ¥Ôª²âÊÔÓÖ³ÆÄ£¿é²âÊÔ£¬Õë¶ÔÈí¼þÉè¼ÆÖеÄ×îСµ¥Î»¡ª¡ª³ÌÐòÄ£¿é£¬½øÐÐÕýÈ·ÐÔ¼ì²éµÄ²âÊÔ¹¤×÷¡£

¼¯³É²âÊÔ

¼¯³É²âÊÔÓÖ½Ð×é×°²âÊÔ£¬Í¨³£ÔÚµ¥Ôª²âÊԵĻù´¡ÉÏ£¬½«ËùÓгÌÐòÄ£¿é½øÐÐÓÐÐòµÄ¡¢µÝÔö²âÊÔ¡£Öصã²âÊÔ²»Í¬Ä£¿éµÄ½Ó¿Ú²¿·Ö

ϵͳ²âÊÔ

Ö¸µÄÊǽ«Õû¸öÈí¼þϵͳ¿´³ÉÒ»¸öÕûÌå½øÐвâÊÔ£¬°üÀ¨¶Ô¹¦ÄÜ¡¢ÐÔÄÜÒÔ¼°Èí¼þËùÔËÐеÄÈíÓ²¼þ»·¾³½øÐвâÊÔ¡£

ÑéÊÕ²âÊÔ

Ö¸°´ÕÕÏîÄ¿ÈÎÎñÊé»òºÏͬ¡¢¹©ÐèË«·½Ô¼¶¨µÄÑéÊÕÒÀ¾ÝÎĵµ½øÐеĶÔÕû¸öϵͳµÄ²âÊÔÓëÆÀÉ󣬾ö¶¨ÊÇ·ñ½ÓÊÕ»ò¾ÜÊÕϵͳ

°´ÊÇ·ñÔËÐл®·Ö

¾²Ì¬²âÊÔ

ÊÇÖ¸²»Êµ¼ÊÔËÐб»²âÈí¼þ£¬¶øÖ»ÊǾ²Ì¬µØ¼ì²é³ÌÐò´úÂë¡¢½çÃæ»òÎĵµÖпÉÄÜ´æÔڵĴíÎó¹ý³Ì

¶¯Ì¬²âÊÔ

ÊÇָʵ¼ÊÔËÐб»²â³ÌÐò£¬ÊäÈëÏàÓ¦µÄ²âÊÔÊý¾Ý£¬¼ì²éʵ¼ÊÊä³ö½á¹ûºÍÔ¤ÆÚ½á¹ûÊÇ·ñÏà·ûµÄ¹ý³Ì¡£

°´ÊÇ·ñ²é¿´Ô´´úÂë»®·Ö

ºÚºÐ²âÊÔ

Ö¸µÄÊǰѱ»²âµÄÈí¼þ¿´×öÒ»¸öºÚºÐ×Ó£¬²»¹ØÐĺÐ×ÓÀïÃæµÄ½á¹¹ÊÇʲôÑù×Ó£¬Ö»¹ØÐÄÈí¼þµÄÊäÈëÊý¾ÝºÍÊä³öÊý¾Ý¡£

°×ºÐ²âÊÔ

Ö¸µÄÊǰѺÐ×Ó´ò¿ª£¬È¥Ñо¿ÀïÃæµÄÔ´´úÂëºÍ³ÌÐò½á¹¹¡£

ÆäËû

»Ø¹é²âÊÔ

ÊÇÖ¸Èí¼þ±»Ð޸ĺóÖØÐ½øÐеIJâÊÔ£¬Öظ´Ö´ÐÐÉÏÒ»¸ö°æ±¾²âÊÔʱµÄÓÃÀý£¬ÊÇΪÁ˱£Ö¤¶ÔÈí¼þËù×öµÄÐÞ¸ÄûÓÐÒýÈëеĴíÎó¶øÖظ´½øÐеIJâÊÔ¡£

ðÑ̲âÊÔ

ÊÇÖ¸ÔÚ¶ÔÒ»¸öа汾½øÐÐϵͳ´ó¹æÄ£µÄ²âÊÔ֮ǰ£¬ÏÈÑéÖ¤Ò»ÏÂÈí¼þµÄ»ù±¾¹¦ÄÜÊÇ·ñʵÏÖ£¬ÊÇ·ñ¾ß±¸¿É²âÐÔ¡£

Ëæ»ú²âÊÔ

ÊÇÖ¸²âÊÔÖÐËùÓеÄÊäÈëÊý¾Ý¶¼ÊÇËæ»úÉú³ÉµÄ£¬ÆäÄ¿µÄÊÇÄ£ÄâÓû§µÄÕæÊµ²Ù×÷£¬²¢·¢ÏÖһЩ±ßÔµÐԵĴíÎó¡£

ATDD,TDD,BDD,DDD

ATDD

ATDD£º Acceptance Test Driven Development£¨ÑéÊÕ²âÊÔÇý¶¯¿ª·¢£©

TDD Ö»ÊÇ¿ª·¢ÈËÔ±µÄÖ°Ôð£¬Í¨¹ýµ¥Ôª²âÊÔÓÃÀýÀ´Çý¶¯¹¦ÄÜ´úÂëµÄʵÏÖ¡£ÔÚ×¼±¸ÊµÊ©Ò»¸ö¹¦ÄÜ»òÌØÐÔ֮ǰ£¬Ê×ÏÈÍŶÓÐèÒª¶¨Òå³öÆÚÍûµÄÖÊÁ¿±ê×¼ºÍÑéÊÕϸÔò£¬ÒÔÃ÷È·¶øÇÒ´ï³É¹²Ê¶µÄÑéÊÕ²âÊԼƻ®£¨°üº¬Ò»ÏµÁвâÊÔ³¡¾°£©À´Çý¶¯¿ª·¢ÈËÔ±µÄTDDʵ¼ùºÍ²âÊÔÈËÔ±µÄ²âÊԽű¾¿ª·¢¡£ÃæÏò¿ª·¢ÈËÔ±£¬Ç¿µ÷ÈçºÎʵÏÖϵͳÒÔ¼°ÈçºÎ¼ìÑé¡£

TDD

TDD£º Test-driven development £¨²âÊÔÇý¶¯¿ª·¢£©

ÊÇÒ»ÖÖʹÓÃ×Ô¶¯»¯µ¥Ôª²âÊÔÀ´Íƶ¯Èí¼þÉè¼Æ²¢Ç¿ÖÆÒÀÀµ¹ØÏµ½âñîµÄ¼¼Êõ¡£Ê¹ÓÃÕâÖÖ×ö·¨µÄ½á¹ûÊÇÒ»Ì×È«ÃæµÄµ¥Ôª²âÊÔ£¬¿ÉËæÊ±ÔËÐУ¬ÒÔÌṩÈí¼þ¿ÉÒÔÕý³£¹¤×÷µÄ·´À¡¡£

²âÊÔÇý¶¯¿ª·¢ÊÇÃô½Ý¿ª·¢ÖеÄÒ»ÏîºËÐÄʵ¼ùºÍ¼¼Êõ£¬Ò²ÊÇÒ»ÖÖÉè¼Æ·½·¨ÂÛ¡£TDDµÄÔ­ÀíÊÇÔÚ¿ª·¢¹¦ÄÜ´úÂë֮ǰ£¬Ïȱàдµ¥Ôª²âÊÔÓÃÀý´úÂ룬²âÊÔ´úÂëÈ·¶¨ÐèÒª±àдʲô²úÆ·´úÂë¡£TDDµÄ»ù±¾Ë¼Â·¾ÍÊÇͨ¹ý²âÊÔÀ´Íƶ¯Õû¸ö¿ª·¢µÄ½øÐУ¬µ«²âÊÔÇý¶¯¿ª·¢²¢²»Ö»Êǵ¥´¿µÄ²âÊÔ¹¤×÷£¬¶øÊǰÑÐèÇó·ÖÎö£¬Éè¼Æ£¬ÖÊÁ¿¿ØÖÆÁ¿»¯µÄ¹ý³Ì¡£TDDÊ×ÏÈ¿¼ÂÇʹÓÃÐèÇ󣨶ÔÏó¡¢¹¦ÄÜ¡¢¹ý³Ì¡¢½Ó¿ÚµÈ£©£¬Ö÷ÒªÊDZàд²âÊÔÓÃÀý¿ò¼Ü¶Ô¹¦ÄܵĹý³ÌºÍ½Ó¿Ú½øÐÐÉè¼Æ£¬¶ø²âÊÔ¿ò¼Ü¿ÉÒÔ³ÖÐø½øÐÐÑéÖ¤¡£¡£

BDD

BDD:Behavior-Driven Development (ÐÐΪÇý¶¯¿ª·¢)

ÐÐΪÇý¶¯¿ª·¢ÊÇÒ»ÖÖÃô½ÝÈí¼þ¿ª·¢µÄ¼¼Êõ£¬Ëü¹ÄÀøÈí¼þÏîÄ¿ÖеĿª·¢Õß¡¢QAºÍ·Ç¼¼ÊõÈËÔ±»òÉÌÒµ²ÎÓëÕßÖ®¼äµÄЭ×÷¡£Ö÷ÒªÊÇ´ÓÓû§µÄÐèÇó³ö·¢£¬Ç¿µ÷ϵͳÐÐΪ¡£BDD×î³õÊÇÓÉDan NorthÔÚ2003ÄêÃüÃû£¬Ëü°üÀ¨ÑéÊÕ²âÊԺͿͻ§²âÊÔÇý¶¯µÈµÄ¼«ÏÞ±à³ÌµÄʵ¼ù£¬×÷Ϊ¶Ô²âÊÔÇý¶¯¿ª·¢µÄ»ØÓ¦¡£

DDD

DDD£ºÁìÓòÇý¶¯¿ª·¢£¨Domain Drive Design£©

DDDÖ¸µÄÊÇDomain Drive Design£¬Ò²¾ÍÊÇÁìÓòÇý¶¯¿ª·¢,DDDʵ¼ÊÉÏÒ²Êǽ¨Á¢ÔÚÕâ¸ö»ù´¡Ö®ÉÏ£¬ÒòΪËü¹Ø×¢µÄÊÇService²ãµÄÉè¼Æ£¬×ÅÖØÓÚÒµÎñµÄʵÏÖ,½«·ÖÎöºÍÉè¼Æ½áºÏÆðÀ´£¬²»ÔÙʹËûÃÇ´¦ÓÚ·ÖÁѵÄ״̬£¬Õâ¶ÔÓÚÎÒÃÇÕýÈ·ÍêÕûµÄʵÏÖ¿Í»§µÄÐèÇó£¬ÒÔ¼°½¨Á¢Ò»¸ö¾ßÓÐÒµÎñÉìËõÐÔµÄÄ£ÐÍ¡£

Angularµ¥Ôª²âÊÔ

Unit Test(µ¥Ôª²âÊÔ)

¶ÔÕýʽµÄÏîÄ¿½øÐе¥Ôª²âÊÔÊDZØÐëµÄ£¬Èç¹ûÑ¡ÔñʹÓÃTDD(²âÊÔÇý¶¯¿ª·¢)·½·¨£¬ÔòÎ޹ؽôÒª£¬·ñÔòʹÓÃËü½«»á²úÉúºÜ¶àºÃ´¦¡£

ÔÚ±¾ÎÄÖУ¬ÎÒÃÇÊ×Ïȼòµ¥µØÌáµ½µ¥Ôª²âÊԵĺô¦£¬È»ºóÎÒÃǽ«´´½¨Ò»¸öAngularµ¥Ôª²âÊÔµÄÍêÕûʾÀý£¬Ê¹ÓÃjasmineºÍkarma¡£

KarmaµÄ½éÉÜ

KarmaÊÇTestacularµÄÐÂÃû×Ö£¬ÔÚ2012Äêgoogle¿ªÔ´ÁËTestacular£¬2013ÄêTestacular¸ÄÃûΪKarma¡£KarmaÊÇÒ»¸öÈÃÈ˸е½·Ç³£ÉñÃØµÄÃû×Ö£¬±íʾ·ð½ÌÖеÄÔµ·Ö£¬Òò¹û±¨Ó¦£¬±ÈCassandraÕâÖÖÃû×Ö¸üÈÃÈ˲²»Í¸£¡

KarmaÊÇÒ»¸ö»ùÓÚNode.jsµÄJavaScript²âÊÔÖ´Ðйý³Ì¹ÜÀí¹¤¾ß£¨Test Runner£©¡£¸Ã¹¤¾ß¿ÉÓÃÓÚ²âÊÔËùÓÐÖ÷Á÷Webä¯ÀÀÆ÷£¬Ò²¿É¼¯³Éµ½CI£¨Continuous integration£©¹¤¾ß£¬Ò²¿ÉºÍÆäËû´úÂë±à¼­Æ÷Ò»ÆðʹÓá£Õâ¸ö²âÊÔ¹¤¾ßµÄÒ»¸öÇ¿´óÌØÐÔ¾ÍÊÇ£¬Ëü¿ÉÒÔ¼à¿Ø(Watch)ÎļþµÄ±ä»¯£¬È»ºó×ÔÐÐÖ´ÐУ¬Í¨¹ýconsole.logÏÔʾ²âÊÔ½á¹û¡£

jasmine½éÉÜ

TDD(Test Driven Development)²âÊÔÇý¶¯¿ª·¢£¬ÊÇÃô½Ý¿ª·¢ÖÐÌá³öµÄ×î¼Ñʵ¼ùÖ®Ò»¡£jasmineºÜÓÐÒâ˼µÄÌá³öÁËBDD(Behavior Driven Development)ÐÐΪÇý¶¯¿ª·¢.

²âÊÔÇý¶¯¿ª·¢£¬¶ÔÈí¼þÖÊÁ¿Æðµ½Á˹淶ÐԵĿØÖÆ¡£Î´Ð´ÊµÏÖ£¬ÏÈд²âÊÔ£¬Ò»¶È³ÉΪJavaÁìÓòÑз¢µÄÊ¥¾­¡£Ëæ×ÅJavascriptÐËÆð£¬¹¦ÄÜÔ½À´Ô½¶à£¬´úÂëÁ¿Ô½À´Ô½´ó£¬¿ª·¢ÈËÔ±ËØÖÊÏà²îÐüÊâ£¬ÕæµÄÓбØÒª½¨Á¢¶Ô´úÂëµÄ¹æ·¶ÐÔ¿ØÖÆ¡£jasmine¾ÍÊÇΪÍŶӺÏ×÷¶øÉú¡£

JasmineÊÇÒ»¸öÓÃÀ´±àдJavascript²âÊԵĿò¼Ü£¬Ëü²»ÒÀÀµÓÚÈÎºÎÆäËüµÄjavascript¿ò¼Ü£¬Ò²²»ÐèÒª¶ÔDOM¡£ËüÓÐÓµÓÐÁéÇɶøÃ÷È·µÄÓï·¨¿ÉÒÔÈÃÄãÇáËɵıàд²âÊÔ´úÂë¡£

jasmineµÄ½á¹¹ºÜ¼òµ¥£º

describe("A suite", function() {
var foo;
beforeEach(function() {
foo = 0;
foo += 1;
});
afterEach(function() {
foo = 0;
});
it("contains spec with an expectation", function() {
expect(true).toBe(true);
});
})

ÿ¸ö²âÊÔ¶¼ÔÚÒ»¸ö²âÊÔ¼¯ÖÐÔËÐУ¬Suite¾ÍÊÇÒ»¸ö²âÊÔ¼¯£¬ÓÃdescribeº¯Êý·â×°¡£ Spec±íʾÿ¸ö²âÊÔÓÃÀý£¬ÓÃitº¯Êý·â×°¡£Í¨¹ýexpectº¯Êý£¬×÷Ϊ³ÌÐò¶ÏÑÔÀ´ÅжÏÏàµÈ¹ØÏµ¡£setup¹ý³ÌÓÃbeforeEachº¯Êý·â×°£¬tearDown¹ý³ÌÓÃafterEach·â×°¡£

µ¥Ôª²âÊԵĺô¦

ÎÒÃÇÏÈÀ´¿´¿´ÎÒÈÏΪÔÚ½â¾ö·½°¸ÖÐʹÓõ¥Ôª²âÊÔµÄÖ÷ÒªÔ­Òò¡­

¸Ä½øÊµÏÖµÄÉè¼Æ

¿ªÊ¼±àдһ¸ö¹¦Äܶø²»¸øÉè¼Æ´øÀ´Ì«¶àµÄ˼¿¼ÊÇ¿ª·¢ÈËÔ±·Ç³£³£¼ûµÄ´íÎó¡£Ê¹Óõ¥Ôª²âÊÔ½«Ç¿ÖÆË¼¿¼²¢ÖØÐ¿¼ÂÇÉè¼Æ£¬Èç¹ûÄúʹÓÃTDD£¬ÔòÓ°Ïì»á¸ü´ó¡£

ÔÊÐíÖØ¹¹

¼ÈÈ»ÄãÒѾ­ÓвâÊÔÈ·±£ÄãËùÓеĶ«Î÷¶¼Äܰ´Ô¤ÆÚ¹¤×÷£¬Äã¿ÉÒÔºÜÈÝÒ×µØÌí¼Ó¶Ô´úÂëµÄÐ޸ģ¬È·±£ÄãûÓÐÌí¼ÓÈκδíÎó¡£

Ìí¼Óй¦Äܶø²»»áÆÆ»µÈκÎÄÚÈÝ

µ±ÄúÌí¼Óй¦ÄÜʱ£¬Äú¿ÉÒÔÔËÐвâÊÔÒÔÈ·±£Äú²»»áÆÆ»µÓ¦ÓóÌÐòµÄÈÎºÎÆäËû²¿·Ö¡£

»¹Óиü¶à£¬µ«ÕâÈý¸öÔÚÈκÎÏîÄ¿É϶¼ÊÇÈç´Ë¾Þ´óµÄʤÀû£¬¶ÔÓÚÎÒÀ´Ëµ£¬ÕâЩӮÀûÊÇ·â±ÕʽµÄ¡£µ«Èç¹ûÄã²»ÏàÐÅ£¬ÈÃÎÒÃÇÔÙÌἸ¸ö¡£

²âÊÔÊǺܺõÄÎĵµ¡£

²âÊÔʹ¿ª·¢ÈËÔ±¶ÔËûÃǵŤ×÷¸üÓÐÐÅÐÄ¡£

Äã¿ÉÒÔ˵ËûÃÇËùÓеĺô¦¶¼ÊÇÒԺܸߵijɱ¾À´ÊµÏֵ쬵«ÊÇÕâÍêÈ«ÊÇ´íÎóµÄ¡£ËùÓÐʹÓõ¥Ôª²âÊÔ¿ÉÄÜ»¨·ÑµÄʱ¼äÓëÒÔºóÔÚÄúÒýÈëй¦ÄÜ»ò½øÐÐÈκÎÖØ¹¹Ê±Òª½ÚÊ¡µÄʱ¼äÏà±È½«»áºÜС¡£»¨ÔÚ½â¾ö´íÎóÉϵÄʱ¼äÒª±ÈûÓÐʹÓõ¥Ôª²âÊÔʱ´ó´óËõ¶Ì¡£

ÎÒÃǽ«´´½¨Ò»¸öʹÓÃAngular£¬JasmineºÍKarmaµÄÓ¦ÓóÌÐòµÄС¶øÍêÕûµÄÀý×Ó¡£

ÕâЩÊÇÎÒÃÇҪ̸ÂÛµÄһЩÊÂÇ飺

½âÊÍһϹ¤¾ßKarmaºÍJasmine

½âÊÍkarmaÅäÖÃ

½âÊÍtestÎļþ

´´½¨µÚÒ»¸ö¼òµ¥µÄ²âÊÔ,½éÉÜJasmineºÍAngular²âÊÔ¹¦ÄÜ

²âÊÔÒ»¸öAngular form,½éÉÜJasmineºÍAngular²âÊÔ¹¦ÄÜ

²âÊÔÒ»¸ö´ø·þÎñµÄ×é¼þ£¬½éÉÜAngular²âÊÔ¹¦ÄÜ

ʹÓÃjasmineºÍkarma´´½¨Ò»¸öAngularÏîÄ¿

ÕýÈçAngularÍŶӽ¨ÒéÎÒÃÇÒªÓÃAngular cliÀ´´´½¨ÎÒÃǵÄÓ¦ÓóÌÐò¡£Í¨¹ýÕâÑù×ö£¬jasmineºÍkarmaµÄÅäÖÿÉÒÔ°ïÎÒÃǽâ¾ö£¬±È½Ï·½±ã¡£

°²×°angular-cli²¢´´½¨Ò»¸öÐÂÏîÄ¿£º

npm install -g @angular/cli

ng new UnitTest ¨Crouting

µ±Äã´´½¨ÏîĿʱ£¬ËùÓеÄÒÀÀµ¹ØÏµ¶¼»á°²×°£¬°üÀ¨ÄãÐèÒª´´½¨²âÊÔµÄËùÓж«Î÷¡£

"@types/jasmine": "~2.8.6",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~8.9.4",
"codelyzer": "~4.2.1",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~1.7.1",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~1.4.2",
"karma-jasmine": "~1.1.1",
"karma-jasmine-html-reporter": "^0.2.2",

jasmine-core:JasmineÊÇÎÒÃǽ«ÓÃÀ´´´½¨²âÊԵĿò¼Ü¡£ËüÓÐÐí¶à¹¦ÄÜ¿ÉÒÔÈÃÎÒÃDZàд²»Í¬ÀàÐ͵IJâÊÔ¡£

karma:KarmaÊÇÎÒÃDzâÊÔµÄÈÎÎñÅܲ½Õß¡£ËüʹÓÃÅäÖÃÎļþÀ´ÉèÖÃÆô¶¯Îļþ£¬±¨¸æ£¬²âÊÔ¿ò¼Ü£¬ä¯ÀÀÆ÷µÈµÈ¡£

ÆäÓàÒÀÀµÖ÷ҪΪ¼Ç¼ÎÒÃǵIJâÊÔ£¬¹¤¾ßʹÓÃkarmaºÍjasmineºÍbrowserµÄ·¢ÉäÆ÷¡£

ÒªÔËÐвâÊÔ£¬Ö»ÐèÔËÐÐÃüÁî¡°ng test¡±¡£¸ÃÃüÁִÐвâÊÔ£¬´ò¿ªä¯ÀÀÆ÷£¬ÏÔʾ¿ØÖÆÌ¨ºÍä¯ÀÀÆ÷±¨¸æ£¬Í¬ÑùÖØÒªµÄÊÇ£¬½«²âÊÔÖ´Ðб£ÁôΪ¼àÊÓģʽ¡£Ò²¾ÍÊǵ±ÎÒÃÇÐ޸Ĺýºó£¬¿ÉÒÔ×Ô¶¯¸üвâÊÔ½á¹û¡£

ng test

Ìáʾ£ºÈç¹ûÏëÒªÖÕÖ¹£¬ÐèÒªÔÚÖÕ¶ËÄÚ°´CTRL+C

KarmaÅäÖÃ

ÈÃÎÒÃÇÀ´¿´¿´ÓÉangular-cli´´½¨µÄkarmaÅäÖÃÎļþ¡£

// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../coverage'),
reports: ['html', 'lcovonly'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};

Äã´ó¸Å¿ÉÒԲµ½ÕâЩÅäÖÃÊôÐԵĴ󲿷ÖÓÃ;£¬µ«ÎÒÃÇÀ´¿´¿´ÆäÖеÄһЩ¡£

frameworks:ÕâÊÇjasmine±»É趨Ϊ²âÊÔ¿ò¼ÜµÄµØ·½¡£Èç¹ûÄãÏëʹÓÃÁíÒ»¸ö¿ò¼Ü£¬ÕâÊÇ×öÕâ¼þʵĵط½¡£

reporters:¸ºÔ𽫲âÊÔ½á¹û¸æÖª¸ø¿ª·¢Õß¡£Í¨³£Êǽ«½á¹û´òÓ¡µ½¿ØÖÆÌ¨ÉÏ£¬»òÕß´æÈëÎļþÖÐ

autoWatch:Èç¹ûÉèÖÃΪtrue£¬Ôò²âÊÔ½«ÒÔWatchģʽÔËÐС£Èç¹ûÄú¸ü¸ÄÈκβâÊÔ²¢±£´æÎļþ£¬²âÊÔ½«ÖØÐÂÉú³É²¢ÖØÐÂÔËÐС£

browsers:ÕâÊÇÄúÉèÖòâÊÔÓ¦¸ÃÔËÐеÄä¯ÀÀÆ÷µÄλÖá£Ä¬ÈÏÇé¿öÏÂÊÇchrome£¬µ«Äã¿ÉÒÔ°²×°ºÍʹÓÃÆäËûä¯ÀÀÆ÷Æô¶¯Æ÷¡£

Test.tsÎļþ

karmaµÄangular-cliÅäÖÃʹÓÃÎļþ¡°test.ts¡±×÷ΪӦÓóÌÐò²âÊÔµÄÈë¿Úµã¡£ÎÒÃÇÀ´¿´¿´Õâ¸öÎļþ;

// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

Äã¿ÉÄÜÓÀÔ¶²»ÐèÒª¸Ä±äÕâ¸öÎļþ£¬µ«ÊÇÓÐʱºò»¹ÊÇ»á¸ü¸ÄµÄ£¬±ÈÈ磺ijһ¸öspecÎļþÅųý²âÊԵȡ£

²âÊÔÌåÑé

ÎÒÃÇÀ´´´½¨ÎÒÃǵĵÚÒ»¸ö²âÊÔ¡£ÐÞ¸Äapp.component.ts¡£Õâ¸ö×é¼þÖ»ÓÐÒ»¸öÊôÐÔ¡°text¡±£¬ÆäֵΪ¡°Angular Unit Testing¡±£¬ËüÊÇÔÚHTMLÖеġ°h1¡±±ê¼ÇÖгÊÏֵģ¬Ëü»¹°üº¬Â·ÓɸùÔªËØºÍһЩ·ÓÉÁ´½Ó¡£ÈÃÎÒÃÇ´´½¨Ò»¸ö²âÊÔÎļþÀ´¼ì²é×é¼þÊÇ·ñʵ¼Ê¾ßÓиÃÊôÐÔ£¬²¢ÇÒʵ¼ÊÉÏÊÇÔÚHTMLÖгÊÏֵġ£

app.component.htmlÎļþ

<h1>{{text}}</h1>
<router-outlet></router-outlet>

app.component.tsÎļþ

import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
text = 'Angular Unit Testing';
}

app.component.spec.tsÎļþ

import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router
/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.text).toEqual('Angular Unit Testing');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent)
.toContain('Welcome to Angular Unit Testing!');
}));
});

´ËʱִÐУº

ng test

»ò

npm test

ng testµÄ³£ÓòÎÊý.

- ¨Ccode-coverage -cc ´úÂ븲¸ÇÂʱ¨¸æ, ĬÈÏÕâ¸öÊDz»¿ªÆôµÄ, ÒòΪÉú³É±¨¸æµÄËÙ¶È»¹ÊDZȽÏÂýµÄ.

- ¨Ccolors Êä³ö½á¹ûʹÓø÷ÖÖÑÕÉ« ĬÈÏ¿ªÆô

- ¨Csingle-run -sr Ö´ÐвâÊÔ, µ«ÊDz»¼ì²âÎļþ±ä»¯ ĬÈϲ»¿ªÆô

- ¨Cprogress °Ñ²âÊԵĹý³ÌÊä³öµ½¿ØÖÆÌ¨ ĬÈÏ¿ªÆô

- ¨Csourcemaps -sm Éú³Ésourcemaps ĬÈÏ¿ªÆô

- ¨Cwatch -w ÔËÐвâÊÔÒ»´Î, ²¢ÇÒ¼ì²â±ä»¯ ĬÈÏ¿ªÆô

ÔÚµ¯³öµÄchromeä¯ÀÀÆ÷´°¿ÚÖÐÏÔʾ£º

ÎÒÃÇÏêϸ½éÉÜÒ»ÏÂÕâ¸ö²âÊÔ´úÂë

µ¼Èë²âÊÔÎļþµÄËùÓÐÒÀÀµÏî

ÕâÀïҪעÒ⣬ÄãÔÚ×é¼þÄÚʹÓõÄÒÀÀµ£¬ÕâÀïÃæÍ¬ÑùÐèÒªµ¼È룬·ñÔò»áÎÞ·¨ÔËÐС£

ʹÓÃdescribe¿ªÊ¼ÎÒÃǵIJâÊÔ

describeÊÇÒ»¸öº¯Êý,Jasmine ¾ÍÊÇʹÓà describe È«¾Öº¯ÊýÀ´²âÊԵġ£

declare function describe(description: string, specDefinitions: () => void): void;

±íʾ·Ö×éÀàËÆ²âÊÔÌ×£¬Ò²¾ÍÊÇÒ»×é²âÊÔÓÃÀý£¬Ö§³ÖdescriptionǶÌס£

Àý×Ó£º

describe('²âÊÔÏÔʾ/Òþ²ØÉ¸Ñ¡Ìõ¼þ', ()=>{

})

ÎÒÃÇÔÚÿ¸ö֮ǰʹÓÃÒì²½¡£Òì²½µÄÄ¿µÄÊÇÈÃËùÓпÉÄܵÄÒì²½´úÂëÔÚ¼ÌÐøÖ®Ç°Íê³É

Jasmine ¾ÍÊÇʹÓà it È«¾Öº¯ÊýÀ´±íʾ£¬ºÍ describe ÀàËÆ£¬×Ö·û´®ºÍ·½·¨Á½¸ö²ÎÊý¡£

ÿ¸ö Spec ÄÚ°üÀ¨¶à¸ö expectation À´²âÊÔÐèÒª²âÊԵĴúÂ룬ֻҪÈκÎÒ»¸ö expectation ½á¹ûΪ false ¾Í±íʾ¸Ã²âÊÔÓÃÀýΪʧ°Ü״̬¡£

describe('demo test', () => {
const VALUE = true;
it('should be true', () => {
expect(VALUE).toBe(VALUE);
})
});

Èç¹ûÓкܶàÐèÒª²âÊԵģ¬¿ÉÒÔ¶à¸öit£º

describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});

¶ÏÑÔ£¬Ê¹Óà expect È«¾Öº¯ÊýÀ´±íʾ£¬Ö»½ÓÊÕÒ»¸ö´ú±íÒª²âÊÔµÄʵ¼ÊÖµ£¬²¢ÇÒÐèÒªÓë Matcher ´ú±íÆÚÍûÖµ¡£

TestBed¿ÉÒÔ°ïÖúÎÒÃÇ´´½¨appʵÀý

´úÂëÖÐÓÐ3¸öit

µÚÒ»¸öΪÒì²½²âÊÔappÊÇ·ñtrue»òfalse

Èç¹ûappÊÇ0£»Á½´ÎÈ¡·´µ±È»ÊÇfalse£»

Èç¹ûappÊÇnull£»Á½´ÎÈ¡·´ÊÇfalse£»

Èç¹ûappÊÇundefined£»Á½´ÎÈ¡·¨ÊÇfalse£»

ÆäÓàµÄ£¬Á½´ÎÈ¡·´ÊÇtrue£»

µÚ¶þ¸öΪÒì²½²âÊÔappÊÇ·ñÓÐtextÊôÐÔ£¬²¢ÇÒÅжÏÖµÊÇ·ñºÍÔ¤ÆÚÏàͬ

µÚÈý¸öΪÒì²½²âÊÔappÊÇ·ñÔÚh1±êÇ©ÖеÄÏÔʾֵΪԤÆÚÖµ

²âÊÔForm

´´½¨Ò»¸öcontact×é¼þ¡£

ng g c contact

Ê×ÏÈÎÒÃÇÐÞ¸Äcontact.component HTMLÎļþ

<div>
{{text}}
</div>
<form id="contact-form" [formGroup]="contactForm" (ngSubmit)="onSubmit()" novalidate>
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
<label class="center-block">Email:
<input class="form-control" formControlName="email">
</label>
<label class="center-block">Text:
<input class="form-control" formControlName="text">
</label>
</div>
<button type="submit"
[disabled]="!contactForm.valid" class="btn btn-success">Save</button>
</form>

ÕâºÜ¼òµ¥£¬Õë¶Ô´úÂë²»×öÈκνâÊÍÁË¡£

ÐÞ¸Äcontact.component.tsÎļþ

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.css']
})
export class ContactComponent {
text = 'contact page';
contactForm: FormGroup;
contact = {
name: '',
email: '',
text: ''
};
submitted = false;
constructor() {
this.createForm();
}
createForm(): void {
this.contactForm = new FormGroup({
'name': new FormControl(this.contact.name, [
Validators.required,
Validators.minLength(4)
]),
'email': new FormControl(this.contact.email, [
Validators.required,
Validators.email
]),
'text': new FormControl(this.contact.text, Validators.required)
});
}
onSubmit(): void {
this.submitted = true;
}
}

Õâ¸ö×é¼þÒ²ºÜÈÝÒ×Àí½â¡£ onSubmitÌá½»º¯ÊýÖ»Êǽ«Ìá½»µÄÊôÐÔ¸ü¸ÄΪtrue¡£

ÐÞ¸Äapp-routing.module.ts

import { ContactComponent } from './contact/contact.component';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
{
path: '',
redirectTo: 'contact',
pathMatch: 'full'
},
{
path: 'contact',
component: ContactComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

´ËʱÖÕ¶ËÖ´ÐУº

npm start

Ð޸IJâÊÔÎļþcontact.component.spec.ts

import { BrowserModule, By } from '@angular/platform-browser';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContactComponent } from './contact.component';
import { DebugElement } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
describe('ContactComponent', () => {
let comp: ContactComponent;
let fixture: ComponentFixture<ContactComponent>;
let de: DebugElement;
let el: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
ContactComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule
]
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(ContactComponent);
comp = fixture.componentInstance;
de = fixture.debugElement.query(By.css('form'));
el = de.nativeElement;
});
}));
it(`should have as text 'contact page'`, async(() => {
expect(comp.text).toEqual('contact page');
}));
it('should set submitted to true', async(() => {
comp.onSubmit();
// Ö±½ÓÄÚ²¿µ÷ÓÃonSubmitº¯Êý£¬ submitted±»¸ü¸ÄΪtrue
expect(comp.submitted).toBeTruthy();
}));
it('form call the onSubmit method', async(() => {
fixture.detectChanges();
spyOn(comp, 'onSubmit');
el = fixture.debugElement.query(By.css('button'))
.nativeElement;
el.click();
// Ä£ÄâÔÚhtml½çÃæÉϵã»÷onSubmit£¬´ËʱÊDz»Äܱ»µã»÷µÄ£¬ÒòΪûÓÐÊäÈ룬ËùÒÔ´ÎÊýÓ¦¸ÃÊÇ0
expect(comp.onSubmit).toHaveBeenCalledTimes(0);
}));
it('form should be invalid', async(() => {
comp.contactForm.controls['email'].setValue('');
comp.contactForm.controls['name'].setValue('');
comp.contactForm.controls['text'].setValue('');
expect(comp.contactForm.valid).toBeFalsy();
}));
it('form should be vaild', async(() => {
comp.contactForm.controls['email'].setValue
('asd@asd.com');
comp.contactForm.controls['name'].setValue('aada');
comp.contactForm.controls['text'].setValue('text');
expect(comp.contactForm.valid).toBeTruthy();
}));
});

´ËʱִÐУº

ng test

ÎÒÃÇÀ´·ÖÎöһϣ¬Õâ¸ö²âÊÔÎļþ×öÁËÄÄЩ¶«Î÷£¿

µ¼ÈëÒÀÀµÄ£¿éBrowserModule,FormsModule,ReactiveFormsModule

ʹÓá±By¡±½«DOMÖеÄformµ¼Èë½øÀ´

µÚÒ»¸ö²âÊÔtextÊôÐÔ

²âÊÔonSubmitº¯Êýµ÷ÓÃ

µÚÈý¸ö²âÊÔʹÓá°fixture¡±¶ÔÏóµÄº¯Êý¡°detectChanges¡±½«×é¼þ״̬ӦÓÃÓÚHTML£¬È»ºó´ÓDOM»ñÈ¡Ìá½»°´Å¥²¢´¥·¢µ¥»÷ʼþ¡£ÔÚ´Ë֮ǰ£¬ÎÒÃÇÔÚ×é¼þµÄ¡°onSubmit¡±¹¦ÄÜÉÏ´´½¨Ò»¸öjasmine ¡°spy¡±¡£×îºó£¬ÎÒÃÇÆÚÍûonSubmitº¯Êý²»»á±»Ö´ÐУ¬ÒòΪÕâ¸ö°´Å¥Ó¦¸Ã±»½ûÓã¬ÒòΪ±íµ¥ÎÞЧ¡£

µÚËĸö²âÊÔ½«ÎÞЧֵÉèÖÃΪ×é¼þ±íµ¥£¬²¢ÆÚÍû±íµ¥ÓÐЧÊôÐÔΪfalse¡£

×îºó£¬ÔÚµÚÎå¸ö²âÊÔÖУ¬ÎÒÃǽ«ÓÐЧֵÉèÖÃΪ±íµ¥²¢ÆÚÍû±íµ¥ÓÐЧÊôÐÔÎªÕæ¡£

СÌáʾ

- detectChanges

ÔÚ²âÊÔÖеÄAngular±ä»¯¼ì²â¡£Ã¿¸ö²âÊÔ³ÌÐò¶¼Í¨¹ýµ÷ÓÃfixture.detectChanges()À´Í¨ÖªAngularÖ´Ðб仯¼ì²â¡£

- By

ByÀàÊÇAngular²âÊÔ¹¤¾ßÖ®Ò»£¬ËüÉú³ÉÓÐÓõÄpredicate¡£ ËüµÄBy.css¾²Ì¬·½·¨²úÉú±ê×¼CSSÑ¡ÔñÆ÷ predicate£¬ÓëJQueryÑ¡ÔñÆ÷ÏàͬµÄ·½Ê½¹ýÂË¡£

²âÊÔ·þÎñservice

µ±ÄãÒª²âÊÔÒ»¸ö´øÓзþÎñµÄ×é¼þʱ£¬¾ÍÏñÎÒÃÇÒѾ­¿´µ½µÄÄÇÑù£¬ÄãÐèÒª½«ÌṩÕßÌí¼Óµ½ÔÚ¡°beforeEach¡±Öд´½¨µÄ²âÊÔÄ£¿é¡£ÊÂÇéÊÇ£¬Äã¿ÉÄܲ»ÏëʹÓÃʵ¼ÊµÄ·þÎñ£¬¶øÊÇÒ»¸öÄ£Äâ°æ±¾£¬ËùÒÔÈÃÎÒÃÇ¿´¿´ÈçºÎ×öµ½ÕâÒ»µã¡­¡­

´´½¨Ò»¸öapp.service·þÎñ

ng g s app

ÐÞ¸Äapp.service.ts

import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AppService {
constructor() { }
getInfo(): string {
return 'test service';
}
}

ÐÞ¸Äapp.component.ts

import { AppService } from './app.service';
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
text = 'Angular Unit Testing';
info: string;
constructor(private service: AppService) {
this.info = this.service.getInfo();
}
}

ÔÚapp.component.spec.tsÄÚÔö¼Ó

×¢ÒâÒýÈëAppService·þÎñ¡£

...
providers: [
AppService
]
...
it('should have as info test service', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.info).toEqual('test service');
}));

ÐÞ¸Äapp.service.spec.ts

import { TestBed, inject, async } from '@angular/core/testing';
import { AppService } from './app.service';
describe('AppService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [AppService]
});
});
it('should be created', inject([AppService], (service: AppService) => {
expect(service).toBeTruthy();
}));
it('should getInfo test service', inject([AppService], (service: AppService) => {
expect(service.getInfo()).toEqual('test service');
}));
});

´ËʱִÐУº

ng test

²âÊÔÈ«²¿Í¨¹ý¡£

СÌáʾ

ÓÐЩʱºòÎÒÃÇÏ£Íû²»ÊÇÒì²½µÄ£¬ÕâʱÐèҪʹÓÃtakeAsyncº¯Êý£¬fakeAsync×îÖØÒªµÄºÃ´¦ÊDzâÊÔ³ÌÐò¿´ÆðÀ´Ïñͬ²½µÄ¡£

it('should show quote after getQuote promise (fakeAsync)', fakeAsync(() => {
fixture.detectChanges();
tick(); // wait for async getQuote
fixture.detectChanges(); // update view with quote
expect(el.textContent).toBe(testQuote);
}));

³£ÓöÏÑÔ·½·¨

Jasmine Ìṩ·Ç³£·á¸»µÄAPI£¬Ò»Ð©³£ÓõÄMatchers£º

toBe() µÈͬ ===

toNotBe() µÈͬ !==

toBeDefined() µÈͬ !== undefined

toBeUndefined() µÈͬ === undefined

toBeNull() µÈͬ === null

toBeTruthy() µÈͬ !!obj

toBeFalsy() µÈͬ !obj

toBeLessThan() µÈͬ <

toBeGreaterThan() µÈͬ >

toEqual() Ï൱ÓÚ ==

toNotEqual() Ï൱ÓÚ !=

toContain() Ï൱ÓÚ indexOf

toBeCloseTo() ÊýÖµ±È½Ïʱ¶¨Ò徫¶È£¬ÏÈËÄÉáÎåÈëºóÔٱȽϡ£

toHaveBeenCalled() ¼ì²éfunctionÊÇ·ñ±»µ÷Óùý

toHaveBeenCalledWith() ¼ì²é´«Èë²ÎÊýÊÇ·ñ±»×÷Ϊ²ÎÊýµ÷Óùý

toMatch() µÈͬ new RegExp().test()

toNotMatch() µÈͬ !new RegExp().test()

toThrow() ¼ì²éfunctionÊÇ·ñ»áÅ׳öÒ»¸ö´íÎó

¶øÕâЩAPI֮ǰÓà not À´±íʾ¸ºÖµµÄÅжϡ£

expect(true).not.toBe(false);

ÕâЩMatchers¼¸ºõ¿ÉÒÔÂú×ãÎÒÃÇÈÕ³£ÐèÇ󣬵±È»ÄãÒ²¿ÉÒÔ¶¨ÖÆ×Ô¼ºµÄMatcherÀ´ÊµÏÖÌØÊâÐèÇó¡£

Mock

ÔÚʵ¼ÊµÄ×é¼þ²âÊÔÖз¢ÏÖ×é¼þÍùÍùÒÀÀµÓÚ·þÎñ¡£¶ø·þÎñÓÖÒÀÀµÓÚÍⲿ×ÊÔ´Èçhttp½»»¥¡¢±¾µØ×ÊÔ´µÈ¡£ÎªÁËÆÁ±ÎÍⲿÒÀÀµ·½±ã×é¼þµÄ²âÊÔ£¬¿ÉÒÔ¶Ô·þÎñ½øÐÐmock¡£¶ÔÓÚ·þÎñµÄmock·½Ê½ÓÐÁ½ÖÖ£ºÎ±Ôì·þÎñʵÀý£¨Ìṩ·þÎñ¸´ÖÆÆ·£©¡¢´ÌÌ½ÕæÊµ·þÎñ¡£ÕâÁ½ÖÖ·½Ê½¶¼Äܹ»´ïµ½mockµÄЧ¹û£¬ÎÒÃÇ¿ÉÒÔÌôѡһÖÖ×îÊʺÏ×Ô¼ºµ±Ç°²âÊÔÎļþµÄ²âÊÔ·½Ê½À´½øÐвâÊÔ¡£

Mock·þÎñʵÀý

µÚÒ»²½£º±àд·þÎñµÄmockÀà

class TaskMonitorStubService extends TaskMonitorService {
public queryTaskList(request: ViewTaskRequest): Observable<any> {
return request.code === -1 ? Observable.of(runningTaskResponse): Observable.of(finishedTashResponse)
}
}

µÚ¶þ²½£ºÔÚconfigureTestingModuleÓÃMockµÄ·þÎñÌæ»»ÕæÊµµÄ·þÎñ

TestBed.configureTestingModule({
imports: [
HttpModule,
TaskMonitorModule
],
Providers: [
{provide: TaskMonitorService, useClass: TaskMonitorStubService}
]
})

´ÌÌ½ÕæÊµ·þÎñ

AngularµÄ·þÎñ¶¼ÊÇͨ¹ý×¢ÈëÆ÷×¢È뵽ϵͳÖеģ¬Í¬ÑùÎÒÃÇ¿ÉÒÔ´Ó¸ùTestBed»ñÈ¡µ½×¢Èë·þÎñµÄʵÀý£¬È»ºó½áºÏ´Ì̽£¨Spy£©¶ÔÕæÊµµÄ·þÎñµÄ·½·¨½øÐÐÌæ»».

let taskMonitorService: TaskMonitorService = TestBe.get(TaskMonitorService);
spyOn(taskMonitorService, 'queryTaskList').and.returnValue(Observable.of
(runningTaskResponse));
 
   
5980 ´Îä¯ÀÀ       31
Ïà¹ØÎÄÕÂ

΢·þÎñ²âÊÔÖ®µ¥Ôª²âÊÔ
һƪͼÎÄ´øÄãÁ˽â°×ºÐ²âÊÔÓÃÀýÉè¼Æ·½·¨
È«ÃæµÄÖÊÁ¿±£ÕÏÌåϵ֮»Ø¹é²âÊÔ²ßÂÔ
È˹¤ÖÇÄÜ×Ô¶¯»¯²âÊÔ̽Ë÷
Ïà¹ØÎĵµ

×Ô¶¯»¯½Ó¿Ú²âÊÔʵ¼ù֮·
jenkins³ÖÐø¼¯³É²âÊÔ
ÐÔÄܲâÊÔÕï¶Ï·ÖÎöÓëÓÅ»¯
ÐÔÄܲâÊÔʵÀý
Ïà¹Ø¿Î³Ì

³ÖÐø¼¯³É²âÊÔ×î¼Ñʵ¼ù
×Ô¶¯»¯²âÊÔÌåϵ½¨ÉèÓë×î¼Ñʵ¼ù
²âÊԼܹ¹µÄ¹¹½¨ÓëÓ¦ÓÃʵ¼ù
DevOpsʱ´úµÄ²âÊÔ¼¼ÊõÓë×î¼Ñʵ¼ù