Êý¾ÝÀàÐÍ¡¢Ä£ÐÍ»ò½Úµã¡ª¡ªÕâЩ¶¼Ö»ÊÇ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): 	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ÔÚ»ù´¡²âÊÔÓÃÀýÖеŤ×÷¡£ËæÒâ³¢ÊÔÁËÕâ¸ö²âÊÔÉèÖò¢¹Û²ìËüµÄ½á¹¹¡£ËæÒâµÄµ÷ÕûÒÑÌṩµÄ²âÊÔÀý³Ì²¢¹Û²ìÕâЩµ÷Õû¶Ô²âÊÔµÄÓ°Ïì¡£ |