#100DaysOfWeb in Python Transcripts
Chapter: Days 81-84: Unit testing web apps
Lecture: Mocking out database access

Login or purchase this course to watch this video and the rest of the course contents.
0:00 We have this beautiful, view model test. We thought everything was so good. We used the testing infrastructure to create a dummy request, and then
0:08 we called it here, and then we're going to search some stuff. But when running it, we saw, actually, no. It's trying to work with the database
0:15 and the database is not set up. We don't even want to set it up. We'd rather have it not talk to the database at all. So in order to make this work
0:23 we're going to do something that's kind of mind blowing. So let's go up here, and import unittest.mock. So the idea is
0:29 if we look down at the view model the problem is that we're calling this function right here. If we go into that function, you'll see that's actually
0:37 doing all sorts of database access. Great, but we don't want to do it. So how do we get around this? What we can do, is in this section
0:44 we can say with, unittest.mock.patch you got to spell things correctly for that to work, okay. So we're coming in here in patch
0:52 and what we pass in, is actually the full package name of the function that we want to alter. So this is going to be
1:00 billtracker.data.repository.get_user_by_id and then what we can do is we can also come down here and say returns, equals, for now just write None.
1:13 But we're going to put something there oh, sorry, excuse me, that would be return value is something there. So the idea is, we can say
1:20 look when you call this function get_user_by_id I don't care what it does, don't actually call it. Instead, just pretend it was called
1:28 and return this value instead. So let's go over here and say test_user. It's going to be a new user, which we're going to import that from our models.
1:36 Say test_user.id = 1. And I believe the test user also probably needs some bills, so we can say bills it's going to be, we'll import the bill
1:47 and just give 'em like, three bills so there's non-trivial information there and now what we can do, is we can say hey, somebody call this function
1:55 just give 'em back that user, ok? So it's as if this came out of the database with that id equals 1, and three empty bills in it.
2:04 So that should be enough to make this all come to life, and work. Remember what happened before was
2:09 this function, threw an exception trying to interact with the database. But now, when it tries to call it this mock is going to change what that means.
2:17 Now, it's in a with clause, because we want other tests to not be affected by this change. It means only within that block of code do we redefine
2:27 what get_user_by_id does, and then it'll put it back. Alright, let's try to run our tests again. Here we go, now like I said, remember I keep
2:34 putting this back to this full space. There's a weird problem, like if I don't have this here watch, you'll see, there's this weird error about bills
2:41 already being defined, it's like, it's redefining what the the SQLAlchemyBase is. Let's not worry about this just put the full name space there.
2:48 But if you do that notice, now it runs. Our test results here, I'm going to expand this out and we can see it ran, it worked in 10 milliseconds.
2:56 How cool is that. So we were able to test this validation that we got this user back, there's no error.
3:03 If for some reason we pass in None, like for some reason the users not found, you'll see that this error is no longer, nothing comes back as something.
3:12 Here you can see: user with id 1, is not found. Right, no user with id 1. So that validation is happening.
3:18 It's not a crash, I mean obviously our assert is crashing but the index view model is doing it's job correctly.
3:26 Alright so you'll see that when you work with these web apps, you often need to use patching to avoid talking to databases
3:33 to avoid talking to web services like I would like to interact with the credit card API without actually calling it. This is the way
3:40 to break free from that.

Talk Python's Mastodon Michael Kennedy's Mastodon