In [9]:
import sys
sys.path.append("..")
Before patching things let us see what we can do with a mock. A mock is placeholder for something else; it can be a module a class a function or a method. For now let us just concentrate on the mock instance itself.
It's to mention that the order of keyword arguments is not preserved.
In [2]:
from concept.mock import Mock, Call, Attribute
mock = Mock(1024, 3.1415926535, "hello", key1=2048, key2=1.707, key3="world")
mock.foo(4096, "another day in paradise", key1=8192)
mock.age = 99
mock.age = 100
age = mock.age
for entry in mock.mock_history():
print(entry)
# precise call
assert Call("__init__", 1024, 3.1415926535, "hello", key1=2048, key2=1.707, key3="world") in mock.mock_history()
# not precise enough
assert Call("__init__") not in mock.mock_history()
# precise attribute
assert Attribute(operation=Attribute.READ, name="age", given_value=100) in mock.mock_history()
# not precise enough
assert Attribute(operation=Attribute.READ, name="age") not in mock.mock_history()
At this moment the patching functionality is not yet implemented. Anyway I have to play a bit with it to get an idea about how it works and what functionality is missing. The chdir and rm are very probably the easy thing when mocking a module. Of course the init in the history is not wanted when mocking a module but that can be adjusted easily since the history is a list and we remove first item. What you can see - or to be more precise - what you can not see is the call of isfile. Since os is now a mock a new mock is provided when accessing path (because path is not known); when accessing isfile on the mock for path the call will be registered there. So here comes the one question how to handle that for patching because usually the patching mechanism usually is about one object.
Also important learning in this section: if we have not yet done the import of the os module we don't get it back with a simple substitution ... we have to remove it from the dictionary. The import mechanism works same ways as caching; things already loaded will not be loaded again.
In [20]:
mocked_module = Mock()
old_os = sys.modules['os']
sys.modules['os'] = mocked_module
import os
os.chdir('/tmp')
os.rm('/tmp/file_that_does_not_exist')
os.path.isfile('/tmp/file_that_does_not_exist')
for entry in mocked_module.mock_history():
print(entry)
# doesn't work as expected
print(old_os)
sys.modules['os'] = old_os
print(os.path.isdir('/tmp'))
# important, otherwise the import will not happen
del sys.modules['os']
# now we are fine
import os
assert os.path.isdir('/tmp')
assert not os.path.isfile('/tmp/file_that_does_not_exist')
In [ ]: