from double import Double
fs=Double('fs')
fs.on_method('volume_of').will_reply('/')
fs.on_method('exists').with_args('/.Trash').will_reply(True)
fs.on_method('has_sticky_bit').with_args('/.Trash').will_reply(True)
La classe รจ questa:class Double:
def __init__(self, name):
self.name = name
self.expectations = {}
self.expectations_with_args = {}
def __getattr__(self, name):
if name in self.expectations:
def fake_method(*args, **kwargs):
return self.expectations[name]
return fake_method
else:
def fake_method(*args, **kwargs):
if (name, args) in self.expectations_with_args.keys():
return self.expectations_with_args[(name,args)]
self._report_unexpected_call(name, *args, **kwargs)
return fake_method
def __call__(self, *args, **kwargs):
self._report_unexpected_call(self.name, args, kwargs)
def on_method(self,name):
class Expectation:
def will_reply(_, return_value):
self.expectations[name] = return_value
def with_args(_,*args):
class Expectation2:
def will_reply(_, return_value):
self.expectations_with_args[(name,args)] = return_value
return Expectation2()
return Expectation()
def _report_unexpected_call(self, method_name, *args, **kwargs):
assert False, ("Unexpected call: %s(%s,%s)" % ( method_name,
','.join(repr(arg) for arg in args),
','.join('%s=%s' %(key,value) for key, value in
kwargs))
+ "Calls expected:%s and %s " %
(self.expectations,
self.expectations_with_args))
Si tratta di una soluzione quick and dirty, molto dirty. Nonostante sia dirty
ha un suo valore. Scrivendola ho imparato che scrivere una classe di Mock non
richiede molto tempo e ora so che potrebbe volerci meno
tempo a scrivere un Mock in Python rispetto a trovare la libreria di mocking
giusta tra quelle disponibili in rete.Credo che questo dipenda essenzialmente dal fatto che Python e' un linguaggio dinamico e che di conseguenza offre costrutti molto piu' semplici per fare metaprogramming rispetto ad altri linguaggi con tipizzazione piu' statica.