Mock Object in Python

Uno dei problemi che ho quando sviluppo in Python e' che non ho ancora trovato una libreria di mocking che mi soddisfi. Non che non ci sia scelta, ci sono almeno tre librerie, peccato che ognuna abbia qualcosa che non mi va. Ieri, mentre stavo scrivendo dei test per trash-cli, ho scritto una classe Mock ex-novo adatta alle mie esigenze. L'esempio di utilizzo e' il seguente:
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.