±à¼ÍƼö: |
±¾ÎÄÀ´×ÔÓÚ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¡±¡£¸ÃÃüÁִÐвâÊÔ£¬´ò¿ªä¯ÀÀÆ÷£¬ÏÔʾ¿ØÖÆÌ¨ºÍä¯ÀÀÆ÷±¨¸æ£¬Í¬ÑùÖØÒªµÄÊÇ£¬½«²âÊÔÖ´Ðб£ÁôΪ¼àÊÓģʽ¡£Ò²¾ÍÊǵ±ÎÒÃÇÐ޸Ĺýºó£¬¿ÉÒÔ×Ô¶¯¸üвâÊÔ½á¹û¡£

Ìáʾ£ºÈç¹ûÏëÒªÖÕÖ¹£¬ÐèÒªÔÚÖÕ¶ËÄÚ°´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µÄ³£ÓòÎÊý.
- ¨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×é¼þ¡£
Ê×ÏÈÎÒÃÇÐÞ¸Ä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 { }
|
´ËʱÖÕ¶ËÖ´ÐУº

Ð޸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();
}));
});
|
´ËʱִÐУº

ÎÒÃÇÀ´·ÖÎöһϣ¬Õâ¸ö²âÊÔÎļþ×öÁËÄÄЩ¶«Î÷£¿
µ¼ÈëÒÀÀµÄ£¿é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·þÎñ
ÐÞ¸Ä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');
}));
}); |
´ËʱִÐУº
²âÊÔÈ«²¿Í¨¹ý¡£
СÌáʾ
ÓÐЩʱºòÎÒÃÇÏ£Íû²»ÊÇÒì²½µÄ£¬ÕâʱÐèҪʹÓÃ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)); |
|