Introduction
We're going to keep this one real short. I'll just make this some code snippets and explanations.
Almost 80%+ of the time, we will have some models within our controllers but it's usually hard to mock those models up. For example we might have a controller with some logic like:
from app.User import User
class MikeController:
def show(self):
return User.find(1).name # returns Mike
But if we go into our test we have something like:
from app.http.controllers.MikeController import MikeController
class TestController:
def setup_method(self):
self.controller = MikeController()
def test_controller_show_returns_mike(self):
assert self.controller.show() == 'Mike'
We are not able to mock the User class because it is hard coded into our controller. It will be pulling in directly from the database. What if we wan't our tests to run without even touching the database?
The Solution
We can simply add that user as a class level attribute:
from app.User import User
class MikeController:
__user__ = User
def show(self):
return self.__user__.find(1).name # returns Mike
and then we can mock up that model:
from app.http.controllers.MikeController import MikeController
class MockUser:
name = 'Mike'
def find(self, index):
return self
class TestController:
def setup_method(self):
self.controller = MikeController()
self.__user__ = MockUser()
def test_controller_show_returns_mike(self):
assert self.controller.show() == 'Mike'
TADA! We can now throw in any model there inside the self.controller.__user__
attribute and it will be mocked when we test the code. This is a nice little tip for testing controllers. Our controllers might look something like:
from app.User import User
from app.Phone import Phone
class MikeController:
__user__ = User
__phone__ = Phone
def show(self):
return self.__user__.find(1).name # returns Mike
def call(self):
return self.__phone__.where('user_id', self.__user__.find(1).id).first()
This is really testable and a cool little trick.
Top comments (0)