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

1Ôª 10Ôª 50Ôª





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



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
ʹÓà Python Mock Àà½øÐе¥Ôª²âÊÔ
 
·­Ò룺µØÓüÐÇÐÇ, Garfielt À´Ô´£º¿ªÔ´ÖйúÉçÇø ·¢²¼ÓÚ 2016-9-7
  2977  次浏览      27
 

Êý¾ÝÀàÐÍ¡¢Ä£ÐÍ»ò½Úµã¡ª¡ªÕâЩ¶¼Ö»ÊÇmock¶ÔÏó¿É³Ðµ£µÄ½ÇÉ«¡£µ«mockÔÚµ¥Ôª²âÊÔÖаçÑÝÒ»¸öʲô½ÇɫĨ£¿ ÓÐʱ£¬ÄãÐèҪΪµ¥Ôª²âÊԵijõʼÉèÖÃ×¼±¸Ò»Ð©¡°ÆäËû¡±µÄ´úÂë×ÊÔ´¡£µ«ÕâЩ×ÊÔ´ÐËÐí»á²»¿ÉÓ㬲»Îȶ¨£¬»òÕßÊÇʹÓÃÆðÀ´Ì«±¿ÖØ¡£Äã¿ÉÒÔÊÔ×ÅÕÒһЩÆäËûµÄ×ÊÔ´Ìæ´ú£»»òÕßÄã¿ÉÒÔͨ¹ý´´½¨Ò»¸ö±»³ÆÎªmockµÄ¶«Î÷À´Ä£ÄâËü¡£MocksÄܹ»ÈÃÎÒÃÇÄ£ÄâÄÇЩÔÚµ¥Ôª²âÊÔÖв»¿ÉÓûòÌ«±¿ÖصÄ×ÊÔ´¡£

ÔÚPythonÖд´½¨mockÊÇͨ¹ýMockÄ£¿éÍê³ÉµÄ¡£Äã¿ÉÒÔͨ¹ýÿ´ÎÒ»¸öÊôÐÔ£¨one-attribute-at-a-time£©»òÒ»¸ö½¡È«µÄ×Öµä¶ÔÏó»òÊÇÒ»¸öÀà½Ó¿ÚÀ´´´½¨mock¡£Ä㻹¿ÉÒÔ¶¨ÒåmockµÄÐÐΪ²¢ÇÒÔÚ²âÊÔ¹ý³ÌÖмì²éËüµÄʹÓá£ÈÃÎÒÃǼÌÐøÌ½ÌÖ¡£

³ý·Çµ¥¶À˵Ã÷£¬ÏÂÃæµÄʾÀý´úÂë¶¼ÊÇÓÃPython2.4дµÄ¡£

²âÊÔ×¼±¸

µäÐ͵IJâÊÔ×¼±¸×îÉÙÓÐÁ½¸ö²¿·Ö¡£Ê×ÏÈÊDzâÊÔ¶ÔÏ󣨺ìÉ«£©£¬ÕâÊDzâÊԵĹØ×¢µã¡£Ëü¿ÉÒÔÊÇÒ»¸ö·½·¨¡¢Ä£¿é»òÕßÀà¡£Ëü¿ÉÒÔ·µ»ØÒ»¸ö½á¹û£¬Ò²¿ÉÒÔ²»·µ»Ø½á¹û£¬µ«ÊÇËü¿ÉÒÔ¸ù¾ÝÊý¾ÝÊý¾Ý»òÕßÄÚ²¿×´Ì¬²úÉú´íÎó»òÕßÒì³££¨Í¼1£©

ͼ1

µÚ¶þ²âÊÔÓÃÀý£¨»ÒÉ«£©£¬Ëü¿ÉÒÔµ¥¶ÀÔËÐÐÒ²¿ÉÒÔ×÷ΪÌ×¼þµÄÒ»²¿·Ö¡£ËüÊÇΪ²âÊÔ¶ÔÏó×¼±¸µÄ£¬Ò²¿ÉÒÔÊDzâÊÔ¶ÔÏóÐèÒªµÄÈÎÒâÊý¾Ý»ò×ÊÔ´¡£ÔËÐÐÒ»¸ö»ò¶à¸ö²âÊÔÊÂÎñ£¬ÔÚÿ¸ö²âÊÔÖмì²é²âÊÔ¶ÔÏóµÄÐÐΪ¡£ÊÕ¼¯²âÊÔ½á¹û²¢ÓÃÒ»¸ö¼ò½à¡¢Ò×¶ÁµÄ¸ñʽ³ÊÏÖ²âÊÔ½á¹û¡£

ÏÖÔÚ£¬ÎªÁË·¢»Ó×÷Óã¬Ò»Ð©²âÊÔ¶ÔÏóÐèÒªÒ»¸ö»ò¶à¸ö×ÊÔ´£¨ÂÌÉ«£©¡£ÕâЩ×ÊÔ´¿ÉÒÔÊÇÆäËûµÄÀà»òÕßÄ£¿é£¬ÉõÖÁÊÇÒ»¸ö·Ç¶ÀÁ¢µÄ½ø³Ì¡£²»ÂÛÆäÐÔÖÊ£¬²âÊÔ×ÊÔ´Êǹ¦ÄÜÐԵĴúÂë¡£ËûÃǵĽÇÉ«ÊÇÖ§³Ö²âÊÔ¶ÔÏ󣬵«ÊÇËûÃDz»ÊDzâÊԵĹØ×¢µã¡£

ʹÓÃMockµÄÀíÓÉ

µ«ÊÇÓÐЩʱºò£¬²âÊÔ×ÊÔ´²»¿ÉÓ㬻òÕß²»Êʺϡ£Ò²ÐíÕâ¸ö×ÊÔ´ÕýÔںͲâÊÔ¶ÔÏó²¢Ðпª·¢ÖУ¬»òÕß²¢²»ÍêÕû»òÕßÊÇÌ«²»Îȶ¨ÒÔÖÁÓÚ²»¿É¿¿¡£

²âÊÔ×ÊÔ´Ì«°º¹ó£¬Èç¹û²âÊÔ×ÊÔ´ÊǵÚÈý·½µÄ²úÆ·£¬Æä¸ß°ºµÄ¼Û¸ñ²»ÊÊÓÃÓÚ²âÊÔ¡£²âÊÔ×ÊÔ´µÄ½¨Á¢¹ýÓÚ¸´ÔÓ£¬Õ¼ÓõÄÓ²¼þºÍʱ¼ä¿ÉÒÔÓÃÓÚ±ðµÄµØ·½¡£Èç¹û²âÊÔ×ÊÔ´ÊÇÒ»¸öÊý¾ÝÔ´£¬½¨Á¢ËüµÄÊý¾Ý¼¯Ä£·ÂÕæÊµÊÀ½çÊÇ·¦Î¶µÄ¡£

²âÊÔ×ÊÔ´ÊDz»¿ÉÔ¤ÖªµÄ¡£Ò»¸öºÃµÄµ¥Ôª²âÊÔÊÇ¿ÉÖØ¸´µÄ£¬ÔÊÐíÄã·ÖÀëºÍʶ±ð¹ÊÕÏ¡£µ«ÊDzâÊÔ×ÊÔ´¿ÉÄܸø³öËæ»úµÄ½á¹û£¬»òÕßËü»áÓв»Í¬µÄÏìӦʱ¼ä¡£¶ø×÷ΪÕâÑùµÄ½á¹û£¬²âÊÔ×ÊÔ´×îÖÕ¿ÉÄܳÉΪһ¸öDZÔڵĽÁ¾ÖÕß¡£

ÕâЩ¶¼ÊÇÄã¿ÉÄÜÏëÒªÓÃmock´úÌæ²âÊÔ×ÊÔ´µÄÔ­Òò¡£mockÏò²âÊÔ¶ÔÏóÌṩһÌ׺ͲâÊÔ×ÊÔ´ÏàͬµÄ·½·¨½Ó¿Ú¡£µ«ÊÇmockÊǸüÈÝÒ×´´½¨ºÍ¹ÜÀí¡£ËüÄÜÏò²âÊÔ¶ÔÏóÌṩºÍÕæÊµµÄ²âÊÔ×ÊÔ´ÏàͬµÄ·½·¨½Ó¿Ú¡£ËüÄÜÌṩȷ¶¨µÄ½á¹û£¬²¢¿ÉÒÔ×Ô¶¨ÒåÒÔÊÊÓÃÓÚÌØ¶¨µÄ²âÊÔ¡£Äܹ»ÈÝÒ׵ĸüУ¬ÒÔ·´Ó³Êµ¼Ê×ÊÔ´µÄ±ä»¯¡£

µ±È»£¬mocks²»ÊÇûÓÐÎÊÌâµÄ¡£Éè¼ÆÒ»¸ö¾«È·µÄmockÊÇÀ§ÄѵÄ,ÌØ±ðÊÇÈç¹ûÄãûÓвâÊÔ×ÊÔ´µÄ¿É¿¿ÐÅÏ¢¡£Äã¿ÉÒÔ³¢ÊÔÕÒµ½Ò»¸ö¿ªÔ´µÄ½Ó¿Ú£¬»òÕßÄãÄܶԲâÊÔ×ÊÔ´µÄ·½·¨½Ó¿Ú½øÐв²⡣ÎÞÂÛÄãÈçºÎÑ¡Ôñ£¬Äã¶¼¿ÉÒÔÔÚÒÔºóÇáËɵĸüÐÂmock,Äã¿ÉÒÔÔÚÊ×Ñ¡×ÊÔ´Öеõ½¸üÏêϸµÄÐÅÏ¢¡£

Ì«¶àµÄmock»áʹ²âÊÔ¹ýÓÚ¸´ÔÓ£¬ÈÃÄã¸ú×Ù´íÎó±äµÃ¸üÀ§ÄÑ¡£×îºÃµÄʵ¼ùÊÇÿ¸ö²âÊÔÓÃÀýÏÞÖÆÊ¹ÓÃÒ»µ½Á½¸ömock£¬»òÕßΪÿ¸ömock/¶ÔÏó¶ÔʹÓöÀÁ¢µÄ²âÊÔÓÃÀý¡£

Mocks¶ÔStubs¶ÔFakes

Mock²»ÊÇÄ£·Â²âÊÔ×ÊÔ´µÄΨһ·½Ê½¡£ÆäËûµÄ½â¾ö·½°¸ÈçstubºÍfakeÒ²ÄÜÌṩÏàͬµÄ·þÎñ¡£Òò´Ë£¬mockºÍÆäËûÁ½ÖÖ½â¾ö·½°¸ÔõÑù±È½Ï£¿ÎªÊ²Ã´Ñ¡Ôñmock¶ø²»ÊÇÑ¡Ôñstub»òÕßfake?

ÈÏʶstub:stubΪ²âÊÔ¶ÔÏóÌṩÁËÒ»Ì×·½·¨½Ó¿Ú£¬ºÍÕæÊµµÄ²âÊÔ×ÊÔ´Ìṩ¸ø²âÊÔ¶ÔÏóµÄ½Ó¿ÚÊÇÏàͬµÄ¡£µ±²âÊÔ¶ÔÏóµ÷ÓÃstub·½·¨Ê±£¬stubÏìÓ¦Ô¤¶¨µÄ½á¹û¡£Ò²¿ÉÒÔ²úÉúÒ»¸öÔ¤¶¨µÄ´íÎó»òÕßÒì³£¡£stub¿ÉÒÔ¸ú×ٺͲâÊÔ¶ÔÏóµÄ½»»¥£¬µ«ÊÇËü²»´¦ÀíÊäÈëµÄÊý¾Ý¡£

fakeÒ²ÌṩÁËÒ»Ì×·½·¨½Ó¿Ú²¢ÇÒÒ²¿ÉÒÔ¸ú×ٺͲâÊÔ¶ÔÏóµÄ½»»¥¡£µ«ÊǺÍstub²»Í¬£¬fakeÕæÕýµÄ´¦ÀíÁË´Ó²âÊÔ¶ÔÏóÊäÈëµÄÊý¾Ý²úÉúµÄ½á¹ûÊÇ»ùÓÚÕâЩÊý¾ÝµÄ¡£¼ò¶øÑÔÖ®£¬fakeÊǹ¦ÄÜÐԵģ¬ËüÊÇÕæÊµ²âÊÔ×ÊÔ´µÄ·ÇÉú²ú°æ¡£Ëüȱ·¦×ÊÔ´µÄÏà»¥ÖÆºâ£¬Ê¹ÓÃÁ˸ü¼òµ¥µÄËã·¨£¬¶øÇÒËüºÜÉÙ´æ´¢ºÍ´«ÊäÊý¾Ý¡£

ʹÓÃfakeºÍstub,Äã¿ÉÒÔÊäÈëÕýÈ·µÄÊý¾Ýµ÷ÓÃÁËÕýÈ·µÄ·½·¨¶Ô²âÊÔ¶ÔÏó½øÐвâÊÔ¡£ÄãÄܲâÊÔ¶ÔÏóÊÇÈçºÎ´¦ÀíÊý¾Ý²¢²úÉú½á¹û£¬µ±³öÏÖ´íÎó»òÕßÒ쳣ʱÊÇÔõÑù·´Ó¦µÄ¡£ÕâЩ²âÊÔ±»³ÆÎª×´Ì¬ÑéÖ¤¡£µ«ÊÇÄãÊÇ·ñÏëÖªµÀ²âÊÔ¶ÔÏóµ÷ÓÃÁËÁ½´ÎÏàͬµÄ·½·¨£¿ÄãÊÇ·ñÏëÖªµÀ²âÊÔ¶ÔÏóÊÇ·ñ°´ÕÕÕýÈ·µÄ˳Ðòµ÷ÓÃÁ˼¸¸ö·½·¨£¿ÕâÖÖ²âÊÔ±»³ÆÎªÐÐΪÑéÖ¤£¬¶øÒª×öµ½ÕâЩ£¬ÄãÐèÒªmocks¡£

ʹÓÃPython Mock

ÔÚPythonÖÐMockÄ£¿éÊÇÓÃÀ´´´½¨ºÍ¹ÜÀímock¶ÔÏóµÄ¡£¸ÃÄ£¿éÊÇMichael FoordµÄÐÄѪ½á¾§£¬ËüÊÇPython3.0µÄ±ê׼ģ¿é¡£Òò´ËÔÚPython2.4~2.7ÖУ¬Äã²»µÃ²»×Ô¼º°²×°Õâ¸öÄ£¿é¡£Äã¿ÉÒÔ Python Package Index website´Ó»ñµÃMockÄ£¿é×îеİ汾¡£

»ùÓÚÄãµÄmock¶ÔÏó£¬MockÄ£¿éÌṩÁËÉÙÁ¿µÄÀࡣΪÁ˸ıäÔËÐÐÖеÄmockÉõÖÁÌṩÁ˲¹¶¡»úÖÆ¡£µ«ÊÇÏÖÔÚ£¬ÎÒÃǹØ×¢Ò»¸öÀࣺMockÀà¡£

ͼ2ÖÐÏÔʾÁËMockÀࣨÂÌÉ«£©µÄ»ù±¾½á¹¹¡£Ëü¼Ì³ÐÓÚÁ½¸ö¸¸ÀࣺNonCallableMockºÍCallableMixin£¨»ÒÉ«£©¡£NonCallableMock¶¨ÒåÁËmock¶ÔÏóËùÐèµÄÀý³Ì¡£ËüÖØÔØÁ˼¸¸öħ·¨·½·¨£¬¸øËûÃǶ¨ÒåÁËȱʡµÄÐÐΪ¡£ÎªÁ˸ú×ÙmockµÄÐÐΪ£¬ËüÌṩÁ˶ÏÑÔÀý³Ì¡£CallableMixin¸üÐÂÁËmock¶ÔÏ󻨵÷µÄħ·¨·½·¨¡£·´¹ýÀ´£¬Á½¸ö¸¸Àà¼Ì³ÐÓÚBaseÀࣨºìÉ«£©£¬ÉùÃ÷ÁËmock¶ÔÏóËùÐèµÄÊôÐÔ¡£

ͼ2

×¼±¸Mock

MockÀàÓÐËÄÌ×·½·¨£¨Í¼3£©¡£µÚÒ»Ì×·½·¨ÊÇÀàµÄ¹¹ÔìÆ÷£¬ËüÓÐÁù¸ö¿ÉÑ¡ºÍÒѱê¼ÇµÄ²ÎÊý¡£Í¼ÖÐÏÔʾÁË4¸ö¾­³£Óõ½µÄ²ÎÊý¡£

ͼ3

¹¹ÔìÆ÷µÄµÚÒ»¸ö²ÎÊýÊÇname£¬Ëü¶¨ÒåÁËmock¶ÔÏóµÄΨһ±êʾ·û¡£Listing oneÏÔʾÁËÔõô´´½¨Ò»¸ö±êʾ·ûΪFooµÄmock¶ÔÏómockFoo¡£Çë×¢Òâµ±ÎÒ´òÓ¡mock¶ÔÏó£¨6-9ÐУ©Ê±£¬±êʾ·ûºó½ô¸úµÄÊÇmock¶ÔÏóµÄΨһID¡£

Listing On

from mock import Mock

# create the mock object
mockFoo = Mock(name = "Foo")

print mockFoo
# returns: <Mock name='Foo' id='494864'>
print repr(mockFoo)
# still returns: <Mock name='Foo' id='494864'>

¹¹ÔìÆ÷µÄµÚ¶þ¸ö²ÎÊýÊÇspec¡£ËüÉèÖÃmock¶ÔÏóµÄÊôÐÔ£¬¿ÉÒÔÊÇproperty»òÕß·½·¨¡£ÊôÐÔ¿ÉÒÔÊÇÒ»¸öÁбí×Ö·û´®»òÕßÊÇÆäËûµÄPythonÀà¡£

ΪÁËÑÝʾ£¬ÔÚListing TwoÖУ¬ÎÒÓÐÒ»¸ö´øÈý¸öÏîÄ¿µÄÁбí¶ÔÏófooSpec(µÚ4ÐÐ)£ºpropertyÊôÐÔ_fooValue,·½·¨ÊôÐÔcallFooºÍdoFoo¡£µ±ÎÒ°ÑfooSpec´øÈëÀ๹ÔìÆ÷ʱ£¨µÚ7ÐУ©£¬mockFoo»ñµÃÁËÈý¸öÊôÐÔ£¬ÎÒÄÜÓõã²Ù×÷·û·ÃÎÊËüÃÇ£¨10~15ÐУ©¡£µ±ÎÒ·ÃÎÊÁËÒ»¸öδÉùÃ÷µÄÊôÐÔʱ£¬mockFooÒý·¢AttributeErrorºÍ"faulty"ÊôÐÔ£¨21~14ÐУ©¡£

Listing Two

from mock import Mock

# prepare the spec list
fooSpec = ["_fooValue", "callFoo", "doFoo"]

# create the mock object
mockFoo = Mock(spec = fooSpec)

# accessing the mocked attributes
print mockFoo
# <Mock id='427280'>
print mockFoo._fooValue
# returns <Mock name='mock._fooValue' id='2788112'>
print mockFoo.callFoo()
# returns: <Mock name='mock.callFoo()' id='2815376'>

mockFoo.callFoo()
# nothing happens, which is fine

# accessing the missing attributes
print mockFoo._fooBar
# raises: AttributeError: Mock object has no attribute '_fooBar'
mockFoo.callFoobar()
# raises: AttributeError: Mock object has no attribute 'callFoobar

Listing ThreeÏÔʾÁËspec²ÎÊýµÄÁíÒ»ÖÖÓ÷¨¡£Õâ´Î£¬ÓдøÈý¸öÊôÐÔµÄÀàFoo(4~12ÐÐ)¡£°ÑÀàÃû´«Èë¹¹ÔìÆ÷ÖУ¬ÕâÑù¾Í²úÉúÁËÒ»¸öºÍFooÓÐÏàͬÊôÐÔµÄmock¶ÔÏó£¨18~23ÐУ©¡£ÔٴΣ¬·ÃÎÊÒ»¸öδÉùÃ÷µÄÊôÐÔÒý·¢ÁËAttributeError£¨29~32ÐУ©¡£Ò²¾ÍÊÇ˵£¬ÔÚÁ½¸öÀý×ÓÖУ¬·½·¨ÊôÐÔʱûÓй¦Äܵġ£ÉõÖÁÔÚ·½·¨Óй¦ÄÜ´úÂëʱ£¬µ÷ÓÃmockµÄ·½·¨Ò²Ê²Ã´¶¼²»×ö¡£

Listing Three

from mock import Mock

# The class interfaces
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# create the mock object
mockFoo = Mock(spec = Foo)

# accessing the mocked attributes
print mockFoo
# returns <Mock spec='Foo' id='507120'>
print mockFoo._fooValue
# returns <Mock name='mock._fooValue' id='2788112'>
print mockFoo.callFoo()
# returns: <Mock name='mock.callFoo()' id='2815376'>

mockFoo.callFoo()
# nothing happens, which is fine

# accessing the missing attributes
print mockFoo._fooBar
# raises: AttributeError: Mock object has no attribute '_fooBar'
mockFoo.callFoobar()
# raises: AttributeError: Mock object has no attribute 'callFoobar'

ÏÂÒ»¸ö¹¹ÔìÆ÷²ÎÊýÊÇreturn_value¡£Õ⽫ÉèÖÃmock¶ÔÏóµÄÏìÓ¦µ±Ëü±»Ö±½Óµ÷ÓõÄʱºò¡£ÎÒÓÃÕâ¸ö²ÎÊýÄ£ÄâÒ»¸ö¹¤³§µ÷Óá£

ΪÁËÑÝʾ£¬ÔÚListing FourÖУ¬ÉèÖÃreturn_valueΪ456£¨µÚ4ÐУ©¡£µ±µ÷ÓÃmockFooʱ£¬½«·µ»Ø456µÄ½á¹û£¨9~11ÐУ©¡£ÔÚListing FiveÖУ¬ÎÒ¸øreturn_value´«ÈëÁËÒ»¸öÀàFooµÄʵÀýfooObj£¨15~19ÐУ©¡£ÏÖÔÚ£¬µ±ÎÒµ÷ÓÃmockFooʱ£¬ÎÒ»ñµÃÁËfooObjµÄʵÀý£¨ÏÔʾΪmockObj£©(µÚ24ÐÐ)¡£ºÍListing TwoºÍThree²»Ò»Ñù£¬mockObjµÄ·½·¨ÊÇ´øÓй¦Äܵġ£

Listing Four

from mock import Mock

# create the mock object
mockFoo = Mock(return_value = 456)

print mockFoo
# <Mock id='2787568'>

mockObj = mockFoo()
print mockObj
# returns: 456

Listing Five

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# creating the mock object
fooObj = Foo()
print fooObj
# returns: <__main__.Foo object at 0x68550>

mockFoo = Mock(return_value = fooObj)
print mockFoo
# returns: <Mock id='2788144'>

# creating an "instance"
mockObj = mockFoo()
print mockObj
# returns: <__main__.Foo object at 0x68550>

# working with the mocked instance
print mockObj._fooValue
# returns: 123
mockObj.callFoo()
# returns: Foo:callFoo_
mockObj.doFoo("narf")
# returns: Foo:doFoo:input = narf
<Mock id='428560'>

side_effect²ÎÊýºÍreturn_valueÊÇÏà·´µÄ¡£Ëü¸ømock·ÖÅäÁË¿ÉÌæ»»µÄ½á¹û£¬¸²¸ÇÁËreturn_value¡£¼òµ¥µÄ˵£¬Ò»¸öÄ£Ä⹤³§µ÷Óý«·µ»Øside_effectÖµ£¬¶ø²»ÊÇreturn_value¡£

Listing SixÑÝʾÁËside_effect²ÎÊýµÄÓ°Ïì¡£Ê×ÏÈ£¬´´½¨ÀàFooµÄʵÀýfooObj£¬°ÑËü´«Èëreturn_value²ÎÊý£¨µÚ17ÐУ©¡£Õâ¸ö½á¹ûºÍListing FiveÊÇÀàËÆµÄ¡£µ±Ëü±»µ÷ÓõÄʱºò£¬mockFoo·µ»ØfooObj(µÚ22ÐÐ)¡£È»ºóÎÒÖØ¸´Í¬ÑùµÄ²½Ö裬¸øside_effect²ÎÊý´«ÈëStandardError£¨µÚ28ÐУ©£¬ÏÖÔÚ£¬µ÷ÓÃmockFooÒý·¢ÁËStandardError£¬²»ÔÙ·µ»ØfooObj(29~30ÐÐ)¡£

Listing Six

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# creating the mock object (without a side effect)
fooObj = Foo()

mockFoo = Mock(return_value = fooObj)
print mockFoo
# returns: <Mock id='2788144'>

# creating an "instance"
mockObj = mockFoo()
print mockObj
# returns: <__main__.Foo object at 0x2a88f0>

# creating a mock object (with a side effect)

mockFoo = Mock(return_value = fooObj, side_effect = StandardError)
mockObj = mockFoo()
# raises: StandardError

Listing SevenÏÔʾÁËÁíÒ»¸öÓ°Ïì¡£ÔÚÕâ¸öÀý×ÓÖУ¬´«ÈëÒ»¸öÁбí¶ÔÏófooListµ½À๹ÔìÆ÷ÖУ¨17~18ÐУ©¡£È»ºó£¬Ã¿´ÎÎÒµ÷ÓÃmockFooʱ£¬ËüÁ¬ÐøµÄ·µ»ØÁбíÖеÄÏ20~30ÐУ©¡£Ò»µ©mockFooµ½´ïÁËÁбíµÄĩ⣬µ÷Óý«Òý·¢StopIteration ´íÎó£¨32~34ÐУ©

Listing Seven

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# creating the mock object (with a side effect)
fooObj = FooSpec()

fooList = [665, 666, 667]
mockFoo = Mock(return_value = fooObj, side_effect = fooList)

fooTest = mockFoo()
print fooTest
# returns 665

fooTest = mockFoo()
print fooTest
# returns 666

fooTest = mockFoo()
print fooTest
# returns 667

fooTest = mockFoo()
print fooTest
# raises: StopIteration

Äã¿ÉÒÔ´«ÈëÆäËûµÄ¿Éµü´ú¶ÔÏ󣨼¯ºÏ£¬Ôª×飩µ½side_effct¶ÔÏóÖС£Äã²»ÄÜ´«ÈëÒ»¸ö¼òµ¥¶ÔÏó£¨ÈçÕûÊý¡¢×Ö·û´®µÈ£©£¬ÒòΪÕâЩ¶ÔÏóÊDz»Äܵü´úµÄ£¬ÎªÁËÈüòµ¥¶ÔÏó¿Éµü´ú£¬ÐèÒª½«ËûÃǼÓÈëµ¥Ò»ÏîµÄÁбíÖС£

Mock¶ÏÑÔ

MockÀàµÄÏÂÒ»Ì×·½·¨ÊǶÏÑÔ¡£Ëü½«°ïÖú¸ú×Ù²âÊÔ¶ÔÏó¶Ômock·½·¨µÄµ÷Óá£ËûÃÇÄܺÍunittestÄ£¿éµÄ¶ÏÑÔÒ»Æð¹¤×÷¡£ÄÜÁ¬½Óµ½mock»òÕ߯䷽·¨ÊôÐÔÖ®Ò»¡£ ÓÐÁ½¸öÏàͬµÄ¿ÉÑ¡²ÎÊý£ºÒ»¸ö±äÁ¿ÐòÁУ¬Ò»¸ö¼ü/ÖµÐòÁС£

µÚÒ»¸ö¶ÏÑÔassert_called_with()£¬¼ì²émock·½·¨ÊÇ·ñ»ñµÃÁËÕýÈ·µÄ²ÎÊý¡£µ±ÖÁÉÙÒ»¸ö²ÎÊýÓдíÎóµÄÖµ»òÕßÀàÐÍʱ£¬µ±²ÎÊýµÄÊýÁ¿´íÎóʱ£¬µ±²ÎÊýµÄ˳Ðò´íÎóʱ£¬»òÕßµ±mockµÄ·½·¨¸ù±¾²»´æÔÚÈκβÎÊýʱ£¬Õâ¸ö¶ÏÑÔ½«Òý·¢´íÎó¡£Listing EightÏÔʾÁË¿ÉÒÔÔõÑùʹÓÃÕâ¸ö¶ÏÑÔ¡£ÄǶù£¬ÎÒ×¼±¸ÁËÒ»¸ömock¶ÔÏó£¬ÓÃÀàFoo×÷ΪËüµÄspec²ÎÊý¡£ÎÒµ÷ÓÃÁËÀàµÄ·½·¨doFoo()£¬´«ÈëÁËÒ»¸ö×Ö·û´®×÷ΪÊäÈ롣ʹÓÃassert_called_with()£¬ÎÒ¼ì²é·½·¨ÊÇ·ñ»ñµÃÁËÕýÈ·µÄÊäÈë¡£µÚ20ÐеĶÏÑÔͨ¹ýÁË£¬ÒòΪdoFoo()»ñµÃÁË"narf"µÄÊäÈë¡£µ«ÊÇÔÚµÚ24ÐеĶÏÑÔʧ°ÜÁËÒòΪdoFoo()»ñµÃÁË"zort"£¬ÕâÊÇ´íÎóµÄÊäÈë¡£

Listing Eight

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
pass

def doFoo(self, argValue):
pass

# create the mock object
mockFoo = Mock(spec = Foo)
print mockFoo
# returns <Mock spec='Foo' id='507120'>

mockFoo.doFoo("narf")
mockFoo.doFoo.assert_called_with("narf")
# assertion passes

mockFoo.doFoo("zort")
mockFoo.doFoo.assert_called_with("narf")
# AssertionError: Expected call: doFoo('narf')
# Actual call: doFoo('zort')

Listing NineÏÔʾÁËÉÔ΢²»Í¬µÄÓ÷¨¡£ÔÚÕâ¸öÀý×ÓÖУ¬ÎÒµ÷ÓÃÁËmock·½·¨callFoo()£¬Ê×ÏÈûÓÐÈκÎÊäÈ룬ȻºóÊäÈëÁË×Ö·û´®¡°zort¡±¡£µÚÒ»¸ö¶ÏÑÔͨ¹ýÁË£¨µÚ20ÐУ©£¬ÒòΪcallFoo()²»Ö§³Ö»ñµÃÈκÎÊäÈë¡£¶øµÚ¶þ¸ö¶ÏÑÔʧ°ÜÁË£¨µÚ24ÐУ©ÒòΪÏÔ¶øÒ×¼ûµÄÔ­Òò¡£

Listing Nine

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
pass

def doFoo(self, argValue):
pass

# create the mock object
mockFoo = Mock(spec = Foo)
print mockFoo
# returns <Mock spec='Foo' id='507120'>

mockFoo.callFoo()
mockFoo.callFoo.assert_called_with()
# assertion passes

mockFoo.callFoo("zort")
mockFoo.callFoo.assert_called_with()
# AssertionError: Expected call: callFoo()
# Actual call: callFoo('zort')

ÏÈÒ»¸ö¶ÏÑÔÊÇassert_called_once_with()¡£Ïñassert_called_with()Ò»Ñù£¬Õâ¸ö¶ÏÑÔ¼ì²é²âÊÔ¶ÔÏóÊÇ·ñÕýÈ·µÄµ÷ÓÃÁËmock·½·¨¡£µ«Êǵ±Í¬ÑùµÄ·½·¨µ÷Óó¬¹ýÒ»´Îʱ£¬ assert_called_once_with£¨£©½«Òý·¢´íÎó£¬È»¶øassert_called_with()»áºöÂÔ¶à´Îµ÷Óá£Listing TenÏÔʾÁËÔõÑùʹÓÃÕâ¸ö¶ÏÑÔ¡£ÄǶù£¬ÎÒµ÷ÓÃÁËmock·½·¨callFoo()Á½´Î¡£µÚÒ»´Îµ÷ÓÃʱ£¨ÐÐ19~20£©£¬¶ÏÑÔͨ¹ý¡£µ«ÊÇÔÚµÚ¶þ´Îµ÷ÓõÄʱ£¨ÐÐ23~24£©£¬¶ÏÑÔʧ°Ü£¬·¢ËÍÁË´íÎóÏûÏ¢µ½stdout¡£

Listing Ten

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
pass

def doFoo(self, argValue):
pass

# create the mock object
mockFoo = Mock(spec = Foo)
print mockFoo
# returns <Mock spec='Foo' id='507120'>

mockFoo.callFoo()
mockFoo.callFoo.assert_called_once_with()
# assertion passes

mockFoo.callFoo()
mockFoo.callFoo.assert_called_once_with()
# AssertionError: Expected to be called once. Called 2 times.

¶ÏÑÔassert_any_call()£¬¼ì²é²âÊÔ¶ÔÏóÔÚ²âÊÔÀý³ÌÖÐÊÇ·ñµ÷ÓÃÁ˲âÊÔ·½·¨¡£Ëü²»¹Ümock·½·¨ºÍ¶ÏÑÔÖ®¼äÓжàÉÙÆäËûµÄµ÷Ó᣺ÍÇ°ÃæÁ½¸ö¶ÏÑÔÏà±È½Ï£¬Ç°Á½¸ö¶ÏÑÔ½ö¼ì²é×î½üÒ»´ÎµÄµ÷Óá£

Listing ElevenÏÔʾÁËassert_any_call()¶ÏÑÔÈçºÎ¹¤×÷£ºÈÔÈ»ÊÇͬÑùµÄmock¶ÔÏó£¬spec²ÎÊýÊÇFooÀà¡£µÚÒ»¸öµ÷Ó÷½·¨callFoo()£¨µÚ18ÐУ©£¬½ÓÏÂÀ´µ÷ÓÃÁ½´ÎdoFoo()(ÐÐ19~20)¡£×¢ÒâdoFoo()»ñµÃÁËÁ½¸ö²»Í¬µÄÊäÈë¡£

Listing Eleven

<from mock import Mock

# The mock specification
class Foo(object):
_fooValue = 123

def callFoo(self):
pass

def doFoo(self, argValue):
pass

# create the mock object
mockFoo = Mock(spec = Foo)
print mockFoo
# returns <Mock spec='Foo' id='507120'>

mockFoo.callFoo()
mockFoo.doFoo("narf")
mockFoo.doFoo("zort")

mockFoo.callFoo.assert_any_call()
# assert passes

mockFoo.callFoo()
mockFoo.doFoo("troz")

mockFoo.doFoo.assert_any_call("zort")
# assert passes

mockFoo.doFoo.assert_any_call("egad")
# raises: AssertionError: doFoo('egad') call not found

µÚÒ»¸öassert_any_call()£¨µÚ22ÐУ©Í¨¹ý£¬ËäÈ»Á½´ÎdoFoo()µ÷Óøô¿ªÁ˶ÏÑÔºÍcallFoo()¡£µÚ¶þ¸ö¶ÏÑÔ£¨µÚ28ÐУ©Ò²Í¨¹ýÁË£¬ËäȻһ¸öcallFoo()¸ô¿ªÁËÎÒÃÇÌáµ½µÄdoFoo()(µÚ20ÐÐ)¡£ÁíÒ»·½Ã棬µÚÈý¸ö¶ÏÑÔ£¨µÚ31ÐУ©Ê§°ÜÁË£¬ÒòΪûÓÐÈκÎdoFoo()µÄµ÷ÓÃʹÓÃÁË"egad"µÄÊäÈë¡£

×îºó£¬»¹ÓÐassert_has_calls£¨£©¡£Ëü²é¿´·½·¨µ÷ÓõÄ˳Ðò£¬¼ì²éËûÃÇÊÇ·ñ°´ÕýÈ·µÄ´ÎÐòµ÷Óò¢´øÓÐÕýÈ·µÄ²ÎÊý¡£Ëü´øÓÐÁ½¸ö²ÎÊý£ºÆÚÍûµ÷Ó÷½·¨µÄÁбíºÍÒ»¸ö¿ÉÑ¡ÐüÊâany_order¡£µ±²âÊÔ¶ÔÏóµ÷ÓÃÁË´íÎóµÄ·½·¨£¬µ÷ÓÃÁ˲»ÔÚ´ÎÐòÖеķ½·¨£¬»òÕß·½·¨»ñµÃÁËÒ»¸ö´íÎóµÄÊäÈ룬½«Éú²ú¶ÏÑÔ´íÎó¡£

Listing TwelveÑÝʾÁËassert_has_calls()¶ÏÑÔ¡£ÔÚ18~20ÐУ¬ÎÒµ÷ÓÃÁËÈý¸ö·½·¨£¬ÌṩÁËÁ½¸öÊäÈ롣Ȼºó£¬ÎÒ×¼±¸ÁËÒ»¸öÆÚÍûµ÷ÓõÄÁÐ±í£¨fooCalls£©²¢°ÑÕâ¸öÁÐ±í´«Èëassert_has_calls()£¨22~23ÐУ©¡£ÓÉÓÚÁÐ±íÆ¥ÅäÁË·½·¨µÄµ÷Ó㬶ÏÑÔͨ¹ý¡£

Listing Twelve

from mock import Mock, call

# The mock specification
class Foo(object):
_fooValue = 123

def callFoo(self):
pass

def doFoo(self, argValue):
pass

# create the mock object
mockFoo = Mock(spec = Foo)
print mockFoo
# returns <Mock spec='Foo' id='507120'>

mockFoo.callFoo()
mockFoo.doFoo("narf")
mockFoo.doFoo("zort")

fooCalls = [call.callFoo(), call.doFoo("narf"), call.doFoo("zort")]
mockFoo.assert_has_calls(fooCalls)
# assert passes

fooCalls = [call.callFoo(), call.doFoo("zort"), call.doFoo("narf")]
mockFoo.assert_has_calls(fooCalls)
# AssertionError: Calls not found.
# Expected: [call.callFoo(), call.doFoo('zort'), call.doFoo('narf')]
# Actual: [call.callFoo(), call.doFoo('narf'), call.doFoo('zort')]

fooCalls = [call.callFoo(), call.doFoo("zort"), call.doFoo("narf")]
mockFoo.assert_has_calls(fooCalls, any_order = True)
# assert passes

ÔÚµÚ26ÐУ¬ÎÒ½»»»ÁËÁ½¸ödoFoo()µ÷ÓõÄ˳Ðò¡£µÚÒ»¸ödoFoo()»ñµÃ"zort"µÄÊäÈ룬µÚ¶þ¸ö»ñµÃÁË"narf"¡£Èç¹ûÎÒ´«ÈëÕâ¸öfooCallsµ½assert_has_calls()£¨µÚ27ÐУ©ÖУ¬¶ÏÑÔʧ°Ü¡£µ«ÊÇÈç¹ûÎÒ¸ø²ÎÊýany_order´«Èë²ÎÊýTrue£¬¶ÏÑÔͨ¹ý¡£ÕâÊÇÒòΪ¶ÏÑÔ½«ºöÂÔ·½·¨µ÷ÓõÄ˳Ðò¡£

Listing ThirteenÑÝʾÁËÆäËûµÄÓ÷¨¡£ÔÚfooCallsÁбíÖУ¬ÎÒÌí¼ÓÁ˲»´æÔڵķ½·¨dooFoo()£¨µÚ22ÐУ©¡£È»ºóÎÒ´«ÈëfooCallsµ½assert_has_calls()ÖУ¨µÚ24ÐУ©¡£¶ÏÑÔʧ°Ü£¬Í¨ÖªÎÒÆÚÍûµ÷ÓõÄ˳ÐòºÍÕæÊµ·¢ÉúµÄ˳Ðò²»Æ¥Åä¡£Èç¹ûÎÒ¸øany_order¸³ÖµÎªTrue£¨µÚ30ÐУ©£¬¶ÏÑÔÃû³ÆdooFoo()×÷ΪΥ¹æµÄ·½·¨µ÷Óá£

Listing Thirteen

from mock import Mock, call

# The mock specification
class Foo(object):
_fooValue = 123

def callFoo(self):
pass

def doFoo(self, argValue):
pass

# create the mock object
mockFoo = Mock(spec = Foo)
print mockFoo
# returns <Mock spec='Foo' id='507120'>

mockFoo.callFoo()
mockFoo.doFoo("narf")
mockFoo.doFoo("zort")

fooCalls = [call.callFoo(), call.dooFoo("narf"), call.doFoo("zort")]

mockFoo.assert_has_calls(fooCalls)
# AssertionError: Calls not found.
# Expected: [call.callFoo(), call.dooFoo('narf'), call.doFoo('zort')]
# Actual: [call.callFoo(), call.doFoo('narf'), call.doFoo('zort')]

fooCalls = [call.callFoo(), call.dooFoo("narf"), call.doFoo("zort")]
mockFoo.assert_has_calls(fooCalls, any_order = True)
# AssertionError: (call.dooFoo('narf'),) not all found in call list

ÔÚassert_has_calls()µÄÁ½¸öÀý×ÓÖУ¬×¢Òâµ½¹Ø¼ü×ÖcallÊdzöÏÖÔÚÿ¸ö·½·¨µÄÇ°Ãæ¡£Õâ¸ö¹Ø¼ü×ÖÊÇÒ»¸öhelper¶ÔÏ󣬱ê¼Ç³ömock¶ÔÏóµÄ·½·¨ÊôÐÔ¡£ÎªÁËʹÓÃcall¹Ø¼ü×Ö£¬ÇëÈ·±£Ê¹ÓÃÈçÏµķ½·¨´ÓmockeÄ£¿éµ¼Èëhelper£º

from mock import Mock, call

¹ÜÀíMock

MockÀàµÄµÚÈýÌ×·½·¨ÔÊÐíÄã¿ØÖÆºÍ¹ÜÀímock¶ÔÏó¡£Äã¿ÉÒÔ¸ü¸ÄmockµÄÐÐΪ£¬¸Ä±äËüµÄÊôÐÔ»òÕß½«mock»Ö¸´µ½²âÊÔǰµÄ״̬¡£ÄãÉõÖÁ¿ÉÒÔ¸ü¸Äÿ¸ömock·½·¨»òÕßmock±¾ÉíµÄÏìÓ¦Öµ¡£attach_mock()·½·¨ÈÃÄãÔÚmockÖÐÌí¼ÓµÚ¶þ¸ömock¶ÔÏó¡£Õâ¸ö·½·¨´øÓÐÁ½¸ö²ÎÊý£ºµÚ¶þ¸ömock¶ÔÏó(aMock)ºÍÒ»¸öÊôÐÔÃû³Æ(aName)¡£

Listing Fourteen ÑùʽÁËattach_mock£¨£©·½·¨µÄʹÓá£ÄǶù£¬ÎÒ´´½¨ÁËÁ½¸ömock¶ÔÏómockFooºÍmockBar,ËûÃÇÓв»Í¬spec²ÎÊý£¨µÚ25Ðк͵Ú30ÐУ©¡£ÎÒÓÃattach_mock()·½·¨½«mockBarÌí¼Óµ½mockFooÖУ¬ÃüÃûΪfooBar(µÚ35ÐÐ)¡£Ò»µ©Ìí¼Ó³É¹¦£¬ÎÒ¾ÍÄÜͨ¹ýproperty fooBar·ÃÎʵڶþmock¶ÔÏóºÍËüµÄÊôÐÔ£¨46~53ÐУ©¡£²¢ÇÒÎÒÈÔÈ»¿ÉÒÔ·ÃÎʵÚÒ»¸ömock¶ÔÏómockFooµÄÊôÐÔ¡£

Listing Fourteen

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

class Bar(object):
# instance properties
_barValue = 456

def callBar(self):
pass

def doBar(self, argValue):
pass

# create the first mock object
mockFoo = Mock(spec = Foo)
print mockFoo
# returns <Mock spec='Foo' id='507120'>

# create the second mock object
mockBar = Mock(spec = Bar)
print mockBar
# returns: <Mock spec='Bar' id='2784400'>

# attach the second mock to the first
mockFoo.attach_mock(mockBar, 'fooBar')

# access the first mock's attributes
print mockFoo
# returns: <Mock spec='Foo' id='495312'>
print mockFoo._fooValue
# returns: <Mock name='mock._fooValue' id='428976'>
print mockFoo.callFoo()
# returns: <Mock name='mock.callFoo()' id='448144'>

# access the second mock and its attributes
print mockFoo.fooBar
# returns: <Mock name='mock.fooBar' spec='Bar' id='2788592'>
print mockFoo.fooBar._barValue
# returns: <Mock name='mock.fooBar._barValue' id='2788016'>
print mockFoo.fooBar.callBar()
# returns: <Mock name='mock.fooBar.callBar()' id='2819344'>
print mockFoo.fooBar.doBar("narf")
# returns: <Mock name='mock.fooBar.doBar()' id='4544528'>

configure_mock()·½·¨ÈÃÄãÅúÁ¿µÄ¸ü¸Ämock¶ÔÏó¡£ËüΨһµÄ²ÎÊýÊÇÒ»¸ö¼üÖµ¶ÔÐòÁУ¬Ã¿¸ö¼ü¾ÍÊÇÄãÏëÒªÐ޸ĵÄÊôÐÔ¡£Èç¹ûÄãµÄ¶ÔÏóûÓÐÖ¸¶¨µÄÊôÐÔ£¬configure_mock()½«ÔÚmockÖÐÌí¼ÓÊôÐÔ¡£

Listing fifteenÏÔʾÁËconfigure_mock()·½·¨µÄÔËÓá£ÔٴΣ¬ÎÒ¶¨ÒåÁËÒ»¸öspecΪÀàFooºÍreturn_valueΪ555µÄmock¶ÔÏómockFoo£¨µÚ13ÐУ©¡£È»ºóʹÓÃconfigure_mock()·½·¨¸ü¸Äreturn_valueΪ999£¨µÚ17ÐУ©¡£µ±ÎÒÖ±½Óµ÷ÓÃmockFooʱ£¬»ñµÃµÄ½á¹ûΪ999£¬Ìæ»»ÁËÔ­À´µÄ555¡£

Listing Fifteen

from mock import Mock

class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

mockFoo = Mock(spec = Foo, return_value = 555)
print mockFoo()
# returns: 555

mockFoo.configure_mock(return_value = 999)
print mockFoo()
# returns: 999

fooSpec = {'callFoo.return_value':"narf", 'doFoo.return_value':"zort", 'doFoo.side_effect':StandardError}
mockFoo.configure_mock(**fooSpec)

print mockFoo.callFoo()
# returns: narf
print mockFoo.doFoo("narf")
# raises: StandardError

fooSpec = {'doFoo.side_effect':None}
mockFoo.configure_mock(**fooSpec)
print mockFoo.doFoo("narf")
# returns: zort

½Ó×Å£¬ÎÒ×¼±¸ÁËÒ»¸ö×ֶζÔÏó(fooSpec)£¬¶ÔÁ½¸ömock·½·¨ÉèÖÃÁË·µ»ØÖµ£¬ÎªdoFoo()ÉèÖÃÁËside_effect£¨µÚ21ÐУ©¡£ÎÒ½«fooSpec´«Èëconfigure_mock()£¬×¢ÒâfooSpec´øÓÐǰ׺'**'£¨µÚ22ÐУ©¡£ÏÖÔÚµ÷ÓÃcallFoo()½á¹û·µ»Ø¡°narf¡±¡£µ÷ÓÃdoFoo()£¬ÎÞÂÛÊäÈëʲô£¬Òý·¢StandardError Ðźţ¨ÐÐ24~27£©¡£Èç¹ûÎÒÐÞ¸ÄÁËfooSpec£¬ÉèÖÃdoFoo(£©µÄside_effectµÄֵΪNone,µ±ÎÒµ÷ÓÃdoFoo()ʱ£¬½«µÃµ½½á¹û¡°zort¡±£¨29~32ÐУ©¡£

ÏÂÒ»¸ö·½·¨mock_add_spec()ÈÃÄãÏòmock¶ÔÏóÌí¼ÓеÄÊôÐÔ¡£³ýÁËmock_add_spec()¹¤×÷ÔÚÒ»¸öÒÑ´æÔڵĶÔÏóÉÏÖ®Í⣬ËüµÄ¹¦ÄÜÀàËÆÓÚ¹¹ÔìÆ÷µÄspec²ÎÊý¡£Ëü²Á³ýÁËһЩ¹¹ÔìÆ÷ÉèÖõÄÊôÐÔ¡£Õâ¸ö·½·¨´øÓÐÁ½¸ö²ÎÊý£ºspecÊôÐÔ£¨aSpec£©ºÍspc_set±êÖ¾£¨aFlag£©¡£ÔٴΣ¬spce¿ÉÒÔÊÇ×Ö·û´®Áбí»òÕßÊÇÀà¡£ÒÑÌí¼ÓµÄÊôÐÔȱʡ״̬ÊÇÖ»¶ÁµÄ£¬µ«ÊÇͨ¹ýÉèÖÃspec_set±ê־ΪTrue£¬¿ÉÒÔÈÃÊôÐÔ¿Éд¡£

Listing SixteenÑÝʾÁËmock_add_spec()µÄÔËÓá£mock¶ÔÏómockFoo¿ªÊ¼µÄÊôÐÔÀ´×ÔÓÚÀàFoo(µÚ25ÐÐ)¡£µ±ÎÒ·ÃÎÊÁ½¸öÊôÐÔ£¨_fooValueºÍcallFoo()£©Ê±£¬Îҵõ½½á¹ûÈ·ÈÏËûÃÇÊÇ´æÔڵģ¨29~32ÐУ©¡£

Listing Sixteen

from mock import Mock

# The class interfaces
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

class Bar(object):
# instance properties
_barValue = 456

def callBar(self):
pass

def doBar(self, argValue):
pass

# create the mock object
mockFoo = Mock(spec = Foo)

print mockFoo
# returns <Mock spec='Foo' id='507120'>
print mockFoo._fooValue
# returns <Mock name='mock._fooValue' id='2788112'>
print mockFoo.callFoo()
# returns: <Mock name='mock.callFoo()' id='2815376'>

# add a new spec attributes
mockFoo.mock_add_spec(Bar)

print mockFoo
# returns: <Mock spec='Bar' id='491088'>
print mockFoo._barValue
# returns: <Mock name='mock._barValue' id='2815120'>
print mockFoo.callBar()
# returns: <Mock name='mock.callBar()' id='4544368'>

print mockFoo._fooValue
# raises: AttributeError: Mock object has no attribute '_fooValue'
print mockFoo.callFoo()
# raises: AttributeError: Mock object has no attribute 'callFoo'

È»ºó£¬ÎÒʹÓÃmock_add_spec()·½·¨Ìí¼ÓÀàBarµ½mockFoo(µÚ35ÐÐ)¡£mock¶ÔÏóÏÖÔÚµÄÊôÐÔÒÑÉùÃ÷ÔÚÀàBarÖУ¨39~42ÐУ©¡£Èç¹ûÎÒ·ÃÎÊÈκÎFooÊôÐÔ£¬mock¶ÔÏó½«Òý·¢AttributeError Ðźţ¬±íʾËûÃDz»´æÔÚ£¨44~47ÐУ©¡£

×îºóÒ»¸ö·½·¨resetMock()£¬»Ö¸´mock¶ÔÏóµ½²âÊÔǰµÄ״̬¡£ËüÇå³ýÁËmock¶ÔÏóµÄµ÷ÓÃͳ¼ÆºÍ¶ÏÑÔ¡£Ëü²»»áÇå³ýmock¶ÔÏóµÄreturn_valueºÍside_effectÊôÐÔºÍËüµÄ·½·¨ÊôÐÔ¡£ÕâÑù×öÊÇΪÁËÖØÐÂʹÓÃmock¶ÔÏó±ÜÃâÖØÐ´´½¨mockµÄ¿ªÏú¡£

×îºó£¬ÄãÄܸøÃ¿¸ö·½·¨ÊôÐÔ·ÖÅä·µ»ØÖµ»òÕßside-effect¡£ÄãÄÜͨ¹ýreturn_valueºÍside_effect·ÃÎÊÆ÷×öµ½ÕâЩ¡£ÀýÈ磬°´ÈçϵÄÓï¾äͨ¹ýreturn_value·ÃÎÊÆ÷ÉèÖ÷½·¨callFoo()µÄ·µ»ØÖµÎª"narf"£º

mockFoo.callFoo.return_value = "narf"
°´ÈçϵÄÓï¾äͨ¹ýside_effect·ÃÎÊÆ÷ ÉèÖ÷½·¨callFoo()µÄside-ffectΪTypeError

mockFoo.callFoo.side_effect = TypeError
´«ÈëNoneÇå³ýside-effect

mockFoo.callFoo.side_effect = None
ÄãÒ²¿ÉÒÔÓÃÕâ¸öÁ½¸öÏàͬµÄ·ÃÎÊÆ÷¸Ä±ämock¶ÔÏó¶Ô¹¤³§µ÷ÓõÄÏìÓ¦Öµ

Mockͳ¼Æ

×îºóÒ»Ì×·½·¨°üº¬¸ú×Ùmock¶ÔÏóËù×öµÄÈÎÒâµ÷ÓõķÃÎÊÆ÷¡£µ±mock¶ÔÏó»ñµÃ¹¤³§µ÷ÓÃʱ£¬·ÃÎÊÆ÷called·µ»ØTrue£¬·ñÔò·µ»ØFalse¡£²é¿´Listing SeventeenÖеĴúÂ룬ÎÒ´´½¨ÁËmockFooÖ®ºó£¬called·ÃÎÊÆ÷·µ»ØÁ˽á¹ûFalse(19~20ÐÐ)¡£Èç¹ûÎÒ×öÁËÒ»¸ö¹¤³§µ÷Óã¬Ëü½«·µ»Ø½á¹ûTrue(22~23ÐÐ)¡£µ«ÊÇÈç¹ûÎÒ´´½¨Á˵ڶþ¸ömock¶ÔÏó£¬È»ºóµ÷ÓÃÁËmock·½·¨callFoo()£¨µÚ30ÐУ©?ÔÚÕâ¸öÀý×ÓÖУ¬called·ÃÎÊÆ÷½ö½ö·Å»ØÁËFalse½á¹û£¨31~32ÐУ©¡£

Listing Seventeen

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# create the first mock object
mockFoo = Mock(spec = Foo)
print mockFoo
# returns <Mock spec='Foo' id='507120'>

print mockFoo.called
# returns: False

mockFoo()
print mockFoo.called
# returns: True

mockFoo = Mock(spec = Foo)
print mockFoo.called
# returns: False

mockFoo.callFoo()
print mockFoo.called
# returns: False

·ÃÎÊÆ÷call_count¸ø³öÁËmock¶ÔÏó±»¹¤³§µ÷ÓõĴÎÊý¡£²é¿´Listing EighteenÖеĴúÂë¡£ÎÒ´´½¨mockFooÖ®ºó£¬call_count¸ø³öµÄÆÚÍû½á¹ûΪ0(19~20ÐÐ)¡£µ±ÎÒ¶ÔmockFoo×öÁËÒ»¸ö¹¤³§µ÷ÓÃʱ£¬call_countÔö¼Ó1£¨22~24ÐУ©¡£µ±ÎÒµ÷ÓÃmock·½·¨callFoo()ʱ£¬call_countûÓиı䣨26~28ÐУ©¡£Èç¹ûÎÒ×öÁ˵ڶþ´Î¹¤³§µ÷ÓÃcall_count½«ÔÙÔö¼Ó1¡£

Listing Eighteen

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# create the first mock object
mockFoo = Mock(spec = Foo)
print mockFoo
# returns <Mock spec='Foo' id='507120'>

print mockFoo.call_count
# returns: 0

mockFoo()
print mockFoo.call_count
# returns: 1

mockFoo.callFoo()
print mockFoo.call_count
# returns: 1

·ÃÎÊÆ÷call_args·µ»Ø¹¤³§µ÷ÓÃÒÑÓõIJÎÊý¡£Listing NineteenÑÝʾÁËËüµÄÔËÓ᣶ÔÓÚд´½¨µÄmock¶ÔÏó(mockFoo)£¬call_args·ÃÎÊÆ÷·µ»Ø½á¹ûΪNone(17~21ÐÐ)¡£Èç¹ûÎÒ×öÁËÒ»¸ö¹¤³§µ÷Óã¬ÔÚÊäÈëÖд«Èë"zort"£¬call_args±¨¸æµÄ½á¹ûΪcall('zort')£¨23~25ÐУ©¡£×¢Òâ½á¹ûÖеÄcall¹Ø¼ü×Ö¡£¶ÔÓÚµÚ¶þ¸öûÓÐÊäÈëµÄ¹¤³§µ÷Óã¬call_args·µ»Øcall()£¨27~29ÐУ©¡£µÚÈý¸ö¹¤³§µ÷Óã¬ÊäÈë¡°troz¡±£¬call_args¸ø³ö½á¹ûΪcall('troz')£¨31~33ÐУ©¡£µ«Êǵ±ÎÒµ÷ÓÃmock·½·¨callFoo()ʱ£¬call_args·ÃÎÊÆ÷ÈÔÈ»·µ»Øcall('troz')£¨35~37ÐУ©¡£

Listing Nineteen

#!/usr/bin/python

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# create the first mock object
mockFoo = Mock(spec = Foo, return_value = "narf")
print mockFoo
# returns <Mock spec='Foo' id='507120'>
print mockFoo.call_args
# returns: None

mockFoo("zort")
print mockFoo.call_args
# returns: call('zort')

mockFoo()
print mockFoo.call_args
# returns: call()

mockFoo("troz")
print mockFoo.call_args
# returns: call('troz')

mockFoo.callFoo()
print mockFoo.call_args
# returns: call('troz')

·ÃÎÊÆ÷call_args_list Ò²±¨¸æÁ˹¤³§µ÷ÓÃÖÐÒÑʹÓõIJÎÊý¡£µ«ÊÇcall_args·µ»Ø×î½üʹÓõIJÎÊý£¬¶øcall_args_list·µ»ØÒ»¸öÁÐ±í£¬µÚÒ»ÏîΪ×îÔçµÄ²ÎÊý¡£Listing TwentyÏÔʾÁËÕâ¸ö·ÃÎʵĵÄÔËÓã¬Ê¹ÓÃÁ˺ÍListing NineteenÏàͬµÄ´úÂë¡£

Listing Twenty

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# create the first mock object
mockFoo = Mock(spec = Foo, return_value = "narf")
print mockFoo
# returns <Mock spec='Foo' id='507120'>

mockFoo("zort")
print mockFoo.call_args_list
# returns: [call('zort')]

mockFoo()
print mockFoo.call_args_list
# returns: [call('zort'), call()]

mockFoo("troz")
print mockFoo.call_args_list
# returns: [call('zort'), call(), call('troz')]

mockFoo.callFoo()
print mockFoo.call_args_list
# returns: [call('zort'), call(), call('troz')]

·ÃÎÊÆ÷mothod_calls±¨¸æÁ˲âÊÔ¶ÔÏóËù×öµÄmock·½·¨µÄµ÷Óá£ËüµÄ½á¹ûÊÇÒ»¸öÁбí¶ÔÏó£¬Ã¿Ò»ÏîÏÔʾÁË·½·¨µÄÃû³ÆºÍËüµÄ²ÎÊý¡£
Listing Twenty-oneÑÝʾÁËmethod_callsµÄÔËÓ᣶Ôд´½¨µÄmockFoo£¬method_calls·µ»ØÁË¿ÕÁÐ±í£¨15~19ÐУ©¡£µ±×öÁ˹¤³§µ÷ÓÃʱ£¬Í¬Ñù·µ»Ø¿ÕÁÐ±í£¨21~23ÐУ©¡£µ±ÎÒµ÷ÓÃÁËmock·½·¨callFoo()ʱ£¬method_calls·µ»ØÒ»¸ö´øÒ»ÏîÊý¾ÝµÄÁбí¶ÔÏó£¨25~27ÐУ©¡£µ±ÎÒµ÷ÓÃdoFoo()£¬²¢´«Èë"narf"²ÎÊýʱ£¬method_calls·µ»Ø´øÓÐÁ½ÏîÊý¾ÝµÄÁÐ±í£¨29~31ÐУ©¡£×¢Òâÿ¸ö·½·¨Ãû³ÆÊǰ´ÕÕËüµ÷ÓõÄ˳ÐòÏÔʾµÄ¡£

Listing Twenty-one

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# create the first mock object
mockFoo = Mock(spec = Foo, return_value = "poink")
print mockFoo
# returns <Mock spec='Foo' id='507120'>
print mockFoo.method_calls
# returns []

mockFoo()
print mockFoo.method_calls
# returns []

mockFoo.callFoo()
print mockFoo.method_calls
# returns: [call.callFoo()]

mockFoo.doFoo("narf")
print mockFoo.method_calls
# returns: [call.callFoo(), call.doFoo('narf')]

mockFoo()
print mockFoo.method_calls
# returns: [call.callFoo(), call.doFoo('narf')]

×îºóÒ»¸ö·ÃÎÊÆ÷mock_calls±¨¸æÁ˲âÊÔ¶ÔÏó¶Ômock¶ÔÏóËùÓеĵ÷Ó᣽á¹ûÊÇÒ»¸öÁÐ±í£¬µ«Êǹ¤³§µ÷Óúͷ½·¨µ÷Óö¼ÏÔʾÁË¡£Listing Twenty-twoÑÝʾÕâ¸ö·ÃÎÊÆ÷µÄÔËÓã¬Ê¹ÓÃÁ˺ÍListing Twenty-oneÏàͬµÄ´úÂë

Listing Twenty-two

from mock import Mock

# The mock object
class Foo(object):
# instance properties
_fooValue = 123

def callFoo(self):
print "Foo:callFoo_"

def doFoo(self, argValue):
print "Foo:doFoo:input = ", argValue

# create the first mock object
mockFoo = Mock(spec = Foo, return_value = "poink")
print mockFoo
# returns <Mock spec='Foo' id='507120'>

print mockFoo.mock_calls
# returns []

mockFoo()
print mockFoo.mock_calls
# returns [call()]

mockFoo.callFoo()>
print mockFoo.mock_calls
# returns: [call(), call.callFoo()]

mockFoo.doFoo("narf")
print mockFoo.mock_calls
# returns: [call(), call.callFoo(), call.doFoo('narf')]

mockFoo()
print mockFoo.mock_calls
# returns: [call(), call.callFoo(), call.doFoo('narf'), call()]

ÔÚ²âÊÔÖÐʹÓÃMOCK

Êý¾ÝÀàÐÍ£¬Ä£ÐÍ»òÕ߽ڵ㣬ÕâЩÊÇmock¶ÔÏó¿ÉÄܱ»¼Ù¶¨µÄһЩ½ÇÉ«¡£µ«ÊÇmock¶ÔÏóÔõÑùÊʺϵ¥Ôª²âÊÔÄØ£¿ÈÃÎÒÃÇÒ»ÆðÀ´¿´¿´£¬À´×ÔMartin FowlerµÄÎÄÕÂMocks Aren't Stubs²ÉÈ¡Á˼ò»¯µÄÉèÖá£

ÔÚÕâ¸ö²âÊÔÖУ¬ÉèÖÃÁËÈý¸öÀࣨͼ4£©¡£OrderÀàÊDzâÊÔ¶ÔÏó¡£ËüÄ£ÄâÁ˵¥Ò»ÏîÄ¿µÄ²É¹º¶©µ¥£¬¶©µ¥À´Ô´ÓÚÒ»¸öÊý¾ÝÔ´¡£WarehouseÀàÊDzâÊÔ×ÊÔ´¡£Ëü°üº¬Á˼üÖµ¶ÔµÄÐòÁУ¬¼üÊÇÏîÄ¿µÄÃû³Æ£¬ÖµÊÇ¿ÉÓõÄÊýÁ¿¡£OrderTestÀàÊDzâÊÔÓÃÀý±¾Éí¡£

ͼ4

Listing Twenty-threeÃèÊöÁËOrder¡£OrderÀàÉùÃ÷ÁËÈý¸öÊôÐÔ:ÏîÄ¿Ãû³Æ£¨_orderItem£©£¬ÒªÇóµÄÊýÁ¿£¨_orderAmount£©ºÍÒÑÌîдµÄÊýÁ¿(_orderFilled)¡£ËüµÄ¹¹ÔìÆ÷´øÓÐÁ½¸ö²ÎÊý£¨8~18ÐУ©£¬ÌîÈëµÄÊôÐÔÊÇ_orderItemºÍ_orderAmount¡£ËüµÄ__repr__()·½·¨·µ»ØÁ˹ºÂòÇåµ¥µÄÕªÒª(21~24ÐÐ)¡£

Listing Twenty-three

class Order(object):
# instance properties
_orderItem = "None"
_orderAmount = 0
_orderFilled = -1

# Constructor
def __init__(self, argItem, argAmount):
print "Order:__init__"

# set the order item
if (isinstance(argItem, str)):
if (len(argItem) > 0):
self._orderItem = argItem

# set the order amount
if (argAmount > 0):
self._orderAmount = argAmount

# Magic methods
def __repr__(self):
# assemble the dictionary
locOrder = {'item':self._orderItem, 'amount':self._orderAmount}
return repr(locOrder)

# Instance methods
# attempt to fill the order
def fill(self, argSrc):
print "Order:fill_"

try:
# does the warehouse has the item in stock?
if (argSrc is not None):
if (argSrc.hasInventory(self._orderItem)):
# get the item
locCount = argSrc.getInventory(self._orderItem, self._orderAmount)

# update the following property
self._orderFilled = locCount
else:
print "Inventory item not available"
else:
print "Warehouse not available"
except TypeError:
print "Invalid warehouse"

# check if the order has been filled
def isFilled(self):
print "Order:isFilled_"
return (self._orderAmount == self._orderFilled)

OrderÀඨÒåÁËÁ½¸öʵÀý·½·¨¡£fill()·½·¨´Ó²ÎÊý(argSrc)ÖлñÈ¡Êý¾ÝÔ´¡£Ëü¼ì²éÊý¾ÝÔ´ÊÇ·ñ¿ÉÓã¬Êý¾ÝÔ´µÄÏîÄ¿ÊÇ·ñ´æÔÚÎÊÌ⣨33~34ÐУ©¡£ËüÌá½»ÁËÒ»¸öÉêÇë²¢ÓÃʵ¼Ê·µ»ØµÄÊýÁ¿¸üÐÂ_orderFilled£¨36~39ÐУ©¡£µ±_orderAmountºÍ_orderFilledÓÐÏàͬµÄֵʱ£¬isFilled()·½·¨·µ»ØTrue(48~50ÐÐ)¡£

Listing Twenty-fourÃèÊöÁËWarehouseÀà¡£ËüÊÇÒ»¸ö³éÏóÀ࣬ÉùÃ÷ÁËÊôÐԺͷ½·¨½Ó¿Ú£¬µ«ÊÇûÓж¨Òå·½·¨±¾Éí¡£ÊôÐÔ_houseNameÊDzֿâµÄÃû×Ö£¬¶ø_houseListÊÇËü³ÖÓÐµÄ¿â´æ¡£»¹ÓÐÕâÁ½¸öÊôÐԵķÃÎÊÆ÷¡£

Listing Twenty-four

class Warehouse(object):    
# private properties
_houseName = None
_houseList = None

# accessors
def warehouseName(self):
return (self._houseName)

def inventory(self):
return (self._houseList)


# -- INVENTORY ACTIONS
# set up the warehouse
def setup(self, argName, argList):
&#9;pass

# check for an inventory item
def hasInventory(self, argItem):
pass

# retrieve an inventory item
def getInventory(self, argItem, argCount):
pass

# add an inventory item
def addInventory(self, argItem, argCount):
pass

WarehouseÀàÉùÃ÷ÁËËĸö·½·¨½Ó¿Ú¡£·½·¨setup()´øÓÐÁ½¸ö²ÎÊý£¬ÊÇΪÁ˸üÐÂÕâÁ½¸öÊôÐÔ¡£·½·¨hasInventory()²ÎÊýÊÇÏîÄ¿µÄÃû³Æ£¬Èç¹ûÏîÄ¿ÔÚ¿â´æÖÐÔò·µ»ØTrue¡£·½·¨getInventory()µÄ²ÎÊýÊÇÏîÄ¿µÄÃû³ÆºÍÊýÁ¿¡£Ëü³¢ÊÔ×Å´Ó¿â´æÖп۳ýÊýÁ¿£¬·µ»ØÄÄЩÊdzɹ¦µÄ¿Û³ý¡£·½·¨addInventory()µÄ²ÎÊýÒ²ÊÇÏîÄ¿Ãû³ÆºÍÊýÁ¿¡£Ëü½«ÓÃÕâÁ½¸ö²ÎÊý¸üÐÂ_houseList¡£

Listing Twenty-fiveÊDzâÊÔÓÃÀý±¾Éí£¬orderTestÀà¡£ËûÓÐÒ»¸öÊôÐÔfooSourceÊÇOrderÀàËùÐèµÄmock¶ÔÏó¡£setUp()·½·¨Ê¶±ðÖ´ÐеIJâÊÔÀý³Ì£¨14~16ÐУ©£¬È»ºó´´½¨ºÍÅäÖÃmock¶ÔÏó£¨21~34ÐУ©¡£tearDown()·½·¨Ïòstdout´òÓ¡Ò»¸ö¿ÕÐС£

Listing Twenty-five

import unittest
from mock import Mock, call

class OrderTest(unittest.TestCase):
# declare the test resource
fooSource = None

# preparing to test
def setUp(self):
""" Setting up for the test """
print "OrderTest:setUp_:begin"

# identify the test routine
testName = self.id().split(".")
testName = testName[2]
print testName

# prepare and configure the test resource
if (testName == "testA_newOrder"):
print "OrderTest:setup_:testA_newOrder:RESERVED"
elif (testName == "testB_nilInventory"):
self.fooSource = Mock(spec = Warehouse, return_value = None)
elif (testName == "testC_orderCheck"):
self.fooSource = Mock(spec = Warehouse)
self.fooSource.hasInventory.return_value = True
self.fooSource.getInventory.return_value = 0
elif (testName == "testD_orderFilled"):
self.fooSource = Mock(spec = Warehouse)
self.fooSource.hasInventory.return_value = True
self.fooSource.getInventory.return_value = 10
elif (testName == "testE_orderIncomplete"):
self.fooSource = Mock(spec = Warehouse)
self.fooSource.hasInventory.return_value = True
self.fooSource.getInventory.return_value = 5
else:
print "UNSUPPORTED TEST ROUTINE"

# ending the test
def tearDown(self):
"""Cleaning up after the test"""
print "OrderTest:tearDown_:begin"
print ""

# test: new order
# objective: creating an order
def testA_newOrder(self):
# creating a new order
testOrder = Order("mushrooms", 10)
print repr(testOrder)

# test for a nil object
self.assertIsNotNone(testOrder, "Order object is a nil.")

# test for a valid item name
testName = testOrder._orderItem
self.assertEqual(testName, "mushrooms", "Invalid item name")

# test for a valid item amount
testAmount = testOrder._orderAmount
self.assertGreater(testAmount, 0, "Invalid item amount")

# test: nil inventory
# objective: how the order object handles a nil inventory
def testB_nilInventory(self):
"""Test routine B"""
# creating a new order
testOrder = Order("mushrooms", 10)
print repr(testOrder)

# fill the order
testSource = self.fooSource()
testOrder.fill(testSource)

# print the mocked calls
print self.fooSource.mock_calls

# check the call history
testCalls = [call()]
self.fooSource.assert_has_calls(testCalls)

# ... continued in the next listing

OrderTestÀàÓÐÎå¸ö²âÊÔÀý³Ì¡£ËùÓÐÎå¸ö²âÊÔÀý³ÌÔÚ¿ªÊ¼µÄʱºò¶¼´´½¨ÁËÒ»¸öOrderÀàµÄʵÀý¡£Àý³ÌtestA_newOrder()²âÊÔOrder¶ÔÏóÊÇ·ñ¿ÉÓÃÊÇ·ñÓÐÕýÈ·µÄÊý¾Ý£¨46~60ÐУ©¡£Àý³ÌtestB_nilWarehouse()´´½¨ÁËÒ»¸ö¿ÕµÄmock²¢´«ÈëOrder¶ÔÏóµÄfill()·½·¨£¨64~79ÐУ©¡£Ëü¼ì²éÁËmockµÄµ÷ÓÃÀúÊ·£¬È·±£½ö½ö·¢ÉúÁ˹¤³§µ÷Óá£

Àý³ÌtestC_orderCheck()£¨Listing Twenty-six£©²âÊÔÁËOrder¶ÔÏóÔÚ¿â´æ²»×ãʱµÄ·´Ó¦¡£×î³õ£¬fooSourceµÄhasInventory()·½·¨ÏìÓ¦True£¬getinventory()·½·¨·µ»Ø0¡£²âÊÔÀý³Ì¼ì²éÊÇ·ñ¶©µ¥Î´´ï³É£¬ÊÇ·ñÕýÈ·µÄmock·½·¨±»´øµ÷ÓÃ(16~19ÐÐ)¡£È»ºó²âÊÔÀý³Ì´´½¨ÁËÒ»¸öеÄOrder¶ÔÏó£¬Õâ´ÎÊÇÒ»¸ö²»Í¬µÄÏîÄ¿¡£mock(fooSource)µÄ·½·¨hasInventory()µÄÏìÓ¦ÉèÖÃΪFalse£¨µÚ27ÐУ©¡£ÔٴΣ¬Àý³Ì¼ì²éÊÇ·ñ¶©µ¥Î´´ï³É£¬ÊÇ·ñµ÷ÓÃÁËÕýÈ·µÄmock·½·¨£¨34~37ÐУ©¡£×¢ÒâʹÓÃreset_mock()·½·¨½«fooSource»Ö¸´µ½²âÊÔǰµÄ״̬£¨µÚ28ÐУ©

Listing Twenty-six

class OrderTest(unittest.TestCase):
# ... see previous listing

# test: checking the inventory
# objective: does the order object check for inventory?
def testC_orderCheck(self):
"""Test routine C"""
# creating a test order
testOrder = Order("mushrooms", 10)
print repr(testOrder)

# perform the test
testOrder.fill(self.fooSource)

# perform the checks
self.assertFalse(testOrder.isFilled())
self.assertEqual(testOrder._orderFilled, 0)

self.fooSource.hasInventory.assert_called_once_with("mushrooms")
print self.fooSource.mock_calls

# creating another order
testOrder = Order("cabbage", 10)
print repr(testOrder)

# reconfigure the test resource
self.fooSource.hasInventory.return_value = False
self.fooSource.reset_mock()

# perform the test
testOrder.fill(self.fooSource)

# perform the checks
self.assertFalse(testOrder.isFilled())
self.assertEqual(testOrder._orderFilled, -1)

self.fooSource.hasInventory.assert_called_once_with("cabbage")
print self.fooSource.mock_calls

# ... continued in the next listing

²âÊÔÀý³ÌtestD_orderFilled()£¨Listing Twenty-seven£©Ä£ÄâÁËÒ»¸ö³É¹¦µÄ¶©µ¥ÊÂÎñ¡£fooSourceµÄhasInventory()·½·¨ÏìÓ¦True£¬getinventory()·½·¨·µ»Ø10¡£Àý³Ìµ÷ÓÃfill()·½·¨´«Èëmock¶ÔÏó£¬È»ºó¼ì²é¶©µ¥ÊÇ·ñÒÑÍê³É£¨17~18ÐУ©¡£ËüÒ²¼ì²éÁËÊÇ·ñ²ÉÓÃÕýÈ·µÄ˳ÐòºÍÕýÈ·µÄ²ÎÊýµ÷ÓÃÁË ÕýÈ·µÄmock·½·¨£¨20~24ÐУ©¡£

Listing Twenty-seven

# ... see previous listing

# test: fulfilling an order
# objective: how does the order object behave with a successful transaction
def testD_orderFilled(self):
"""Test routine D"""
# creating a test order
testOrder = Order("mushrooms", 10)
print repr(testOrder)

# perform the test
testOrder.fill(self.fooSource)
print testOrder.isFilled()

# perform the checks
self.assertTrue(testOrder.isFilled())
self.assertNotEqual(testOrder._orderFilled, -1)

self.fooSource.hasInventory.assert_called_once_with("mushrooms")
self.fooSource.getInventory.assert_called_with("mushrooms", 10)

testCalls = [call.hasInventory("mushrooms"), call.getInventory("mushrooms", 10)]
self.fooSource.assert_has_calls(testCalls)

# ... continued in the next listing

²âÊÔÀý³ÌtestE_orderIncomplete()£¨Listing Twenty-eight£©Ä£ÄâÁËÒ»¸öδÍê³ÉµÄÊÂÎñ¡£ÔÚÕâ¸ö²âÊÔÖУ¬fooSourceµÄ·½·¨hasInventory()ÏìÓ¦True,µ«ÊÇgetinventory()·µ»Ø5¡£Àý³Ìµ÷ÓÃfill()·½·¨´«Èëmock¶ÔÏó£¬È»ºó¼ì²éδÍê³ÉµÄ¶©µ¥£¨17~18ÐУ©¡£ ËüÒ²¼ì²éÁËÊÇ·ñ²ÉÓÃÕýÈ·µÄ˳ÐòºÍÕýÈ·µÄ²ÎÊýµ÷ÓÃÁËÕýÈ·µÄmock·½·¨£¨20~25ÐУ©¡£

Listing Twenty-eight

 # ... see previous listing

# test: fulfilling an order
# objective: how does the order object behave with an incomplete transaction
def testE_orderIncomplete(self):
"""Test routine E"""
# creating a test order
testOrder = Order("mushrooms", 10)
print repr(testOrder)

# perform the test
testOrder.fill(self.fooSource)
print testOrder.isFilled()

# perform the checks
self.assertFalse(testOrder.isFilled())
self.assertNotEqual(testOrder._orderFilled, testOrder._orderAmount)

self.fooSource.hasInventory.assert_called_once_with("mushrooms")
self.fooSource.getInventory.assert_called_with("mushrooms", 10)
print self.fooSource.mock_calls

testCalls = [call.hasInventory("mushrooms"), call.getInventory("mushrooms", 10)]
self.fooSource.assert_has_calls(testCalls)

½áÊøÓï

MocksÈÃÎÒÃÇΪµ¥Ôª²âÊÔÄ£ÄâÁËÄÇЩ²»¿ÉÓûòÕßÊÇÌ«ÅÓ´óµÄ×ÊÔ´¡£ÎÒÃÇ¿ÉÒÔÔÚÔËÐÐÖÐÅäÖÃmock£¬ÔÚÌØ¶¨µÄ²âÊÔÖиıäËüµÄÐÐΪ»òÏìÓ¦£¬»òÕßÈÃËüÔÚÇ¡µ±µÄʱºòÅ׳ö´íÎóºÍÒì³£¡£

ÔÚÕâÆªÎÄÕÂÖУ¬ÎÒÃÇ¿´µ½ÁËÔÚµ¥Ôª²âÊÔÖÐÉèÖÃmockµÄºÃ´¦¡£ÎÒÃÇÁ˽âÁËmockºÍfake»òÕßstubµÄÇø±ð¡£ÎÒÃÇÁ˽âÁËÔõÑùÔÚPythonÖд´½¨mock£¬ÔõÑù¹ÜÀíËüºÍÓöÏÑÔ¸ú×ÙËüµÄÐÐΪ¡£ÎÒÃÇÑо¿Á˼òµ¥µÄmockÔÚ»ù´¡²âÊÔÓÃÀýÖеŤ×÷¡£ËæÒâ³¢ÊÔÁËÕâ¸ö²âÊÔÉèÖò¢¹Û²ìËüµÄ½á¹¹¡£ËæÒâµÄµ÷ÕûÒÑÌṩµÄ²âÊÔÀý³Ì²¢¹Û²ìÕâЩµ÷Õû¶Ô²âÊÔµÄÓ°Ïì¡£

   
2977 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

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

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

³ÖÐø¼¯³É²âÊÔ×î¼Ñʵ¼ù
×Ô¶¯»¯²âÊÔÌåϵ½¨ÉèÓë×î¼Ñʵ¼ù
²âÊԼܹ¹µÄ¹¹½¨ÓëÓ¦ÓÃʵ¼ù
DevOpsʱ´úµÄ²âÊÔ¼¼ÊõÓë×î¼Ñʵ¼ù
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]

LoadRunnerÐÔÄܲâÊÔ»ù´¡
Èí¼þ²âÊÔ½á¹û·ÖÎöºÍÖÊÁ¿±¨¸æ
ÃæÏò¶ÔÏóÈí¼þ²âÊÔ¼¼ÊõÑо¿
Éè¼Æ²âÊÔÓÃÀýµÄËÄÌõÔ­Ôò
¹¦ÄܲâÊÔÖйÊÕÏÄ£Ð͵Ľ¨Á¢
ÐÔÄܲâÊÔ×ÛÊö

ÐÔÄܲâÊÔ·½·¨Óë¼¼Êõ
²âÊÔ¹ý³ÌÓëÍŶӹÜÀí
LoadRunner½øÐÐÐÔÄܲâÊÔ
WEBÓ¦ÓõÄÈí¼þ²âÊÔ
ÊÖ»úÈí¼þ²âÊÔ
°×ºÐ²âÊÔ·½·¨Óë¼¼Êõ

ij²©²ÊÐÐÒµ Êý¾Ý¿â×Ô¶¯»¯²âÊÔ
IT·þÎñÉÌ Web°²È«²âÊÔ
IT·þÎñÉÌ ×Ô¶¯»¯²âÊÔ¿ò¼Ü
º£º½¹É·Ý µ¥Ôª²âÊÔ¡¢Öع¹
²âÊÔÐèÇó·ÖÎöÓë²âÊÔÓÃÀý·ÖÎö
»¥ÁªÍøweb²âÊÔ·½·¨Óëʵ¼ù
»ùÓÚSeleniumµÄWeb×Ô¶¯»¯²âÊÔ