<div dir="ltr"><div>Hey all -<br><br>I've recently started working with the 'mock' library in our trial tests, and am looking for some best-practice advice.  I'm really just starting to get used to the library, so it might well have functionality that I'm unaware of or am misusing. <br>

<br>I very quickly ran into a problem where I mistakenly returned a Mock() in the place of a deferred, causing the asserts in callbacks to not be called, and for the test to spuriously pass.<br>
<br>A basic example:<br><br>def test_foo():<br>  d = Mock()<br>  def check_result(res):<br>    self.assertEqual(res.code, expected)  # never called<br>  d.addCallback(check_result)<br>  return d # Mock is truthy, test passes<br>


<br>This occurred where I was mocking some internals of the class under test; something like the below<br><br>A slightly more believable example:<br>== myclass.py ==<br>def some_function(...):<br>  d = self.authenticate()<br>


  d.addCallback(foo) # foo never called<br>  d.addErrback(bar) # bar never called<br>  return d<br><br>== test_myclass.py ==<br>def setUp(self):<br>  self.resource.authenticate = Mock(return_value=Mock())<br><br>def test_foo():<br>


  d = self.resource.some_function<br>  def check_result(res):  # never called<br>    self.assertEqual(res.code, expected) <br>  d.addCallback(check_result)<br>  return d # test passes<br><br>Currently, I'm experimenting with wrapping Mock instantiations by defining common deferred methods on them in advance; this approach would eventually lead to extending Mock itself with this functionality. <br>


<br>def nonDeferredMock():<br></div>    m = Mock()<br><div>    def notimpl(*args, **kwargs):<br>        raise NotImplementedError('You treated a Mock like a Deferred!')<br>    m.addCallback = notimpl<br>    m.addErrback = notimpl<br>


    m.addBoth = notimpl<br>    m.addCallbacks = notimpl<br></div><div>    return m<br></div><div><br></div><div>Another approach might be extending TestCase to check that return values are always not Mock objects. <br><br>


</div><div>Does anyone on the list have experience with this? Obviously, this only happens when mistakes are made when writing tests, but I'd rather have confidence that when my tests pass, that they've passed for the right reasons. <br>


<br></div><div>Another antipattern that I've come across has been:<br><br></div><div>resource.mymethod = Mock(return_value=defer.succeed(None))<br><br></div><div>which works fine for tests in which mymethod() is called once, but always returns the same deferred object if multiple calls are made. What would be a better approach? <br>

<br></div><div>Cheers- <br><br>James<br></div><div><br><br><br><br></div><div><br><br><br><br><br></div></div>