Friday, February 12, 2010

Mocking/stubbing in Django tests again

I've already wrote a bit abouttesting in python. Since that, I've adopted nose and django-nose and I'm quite satisfied with the result.

However, I was still feeling frustrated as I wasn't able to find a way of mocking/stubbing certain modules in my code easily without having duplicate settings.py.

Later I figured out that I'm missing very simple and natural solution for some reason: as views are just functions I could simply import them and do whatever I want with them! The only thing I have to do is to construct HttpRequest object. So, the typical example will look like:



This, however, doesn't make much sense without injecting some mocked stuff. Mock object could be created in setUp like that:



Obviously it's also possible to just imported stubbed versions as well. Anyway, I prefer to go with mocks if I don't need to implement some complicated logic for testing, and create them on fly.

In order to inject this stuff, I modify func_globals property of the function:



So we just use our mocked version of 'foo' instead of 'foo' instead and also override some global function that makes requests to some remote service. This approach doesn't look very clean to my opinion, but it works almost fine. There are some problems with it however: if the view is decorated, we have to figure out how to reach the original function. For standard decorators like login we know that view is accessible as 'view_func' property, but if there are several of them including third party ones, it could be a bit troublesome to figure out what is the original view; on the other hand I don't think it'd be hard to solve these problems.

Anyway, I'm quite happy with this solution.

No comments:

Post a Comment