How to stub an object's __call__ method?

229 views Asked by At

I'm using Nose and Fudge for unit testing. Consider the following class:

class Foo():    
    def __init__(self, some_commandline):
        self._some_commandline = commandline

    def process(self):
        stdout, stderr = self._commandline()
        ...

And a test:

def test_process_commandline(self):
        import StringIO

        # Setup
        fake_stdout = StringIO.StringIO()
        fake_stderr = StringIO.StringIO()
        fake_stdio = fake_stdout, fake_stderr
        fake_cline = (fudge
            .Fake('SomeCommandline')
            .is_a_stub()
            .provides('__call__')
            .returns(fake_stdio))

        sut = Foo(fake_cline)

        # Exercise
        sut.process()

        # Verify
        ...

The error I get is:

...
    stdout, stderr = self._commandline()
TypeError: 'Fake' object is not iterable

The code I'm stubbing has a return line that looks like this (the real version of "SomeCommandline")

return stdout_str, stderr_str

Why am I getting the TypeError saying Fake is not iterable, and how do i stub this method with fudge?

1

There are 1 answers

0
Matt On BEST ANSWER

The stub should be setup using .is_callable() instead of .provides('__call__'):

    fake_cline = (fudge
        .Fake('SomeCommandline')
        .is_callable()
        .returns(fake_stdio))

Also, .is_a_stub() is not needed here because we are stubbing out the method, __call__, directly, which is accessed via the class name SomeCommandLine.