1 00:00:00,000 --> 00:00:02,230 [No Audio] 2 00:00:02,230 --> 00:00:03,404 In this video we're going to use 3 00:00:03,404 --> 00:00:06,070 Mockito to test the LoginController. 4 00:00:06,070 --> 00:00:07,196 So in the previous videos we 5 00:00:07,196 --> 00:00:09,718 coded up this nice layered architecture. 6 00:00:09,718 --> 00:00:10,904 Now we've got that done. 7 00:00:10,904 --> 00:00:12,176 Let's create a test. 8 00:00:12,176 --> 00:00:13,124 So let's suppose we wanted 9 00:00:13,124 --> 00:00:14,890 to test this LoginController. 10 00:00:14,890 --> 00:00:16,876 Okay, so we're going to test the LoginController. 11 00:00:16,876 --> 00:00:20,618 So we're after testing this service method here. 12 00:00:20,618 --> 00:00:22,988 So let's start by testing that. 13 00:00:22,988 --> 00:00:25,472 So if we create a New Java Class, actually 14 00:00:25,472 --> 00:00:27,694 we won't do that, just do shift command 15 00:00:27,694 --> 00:00:29,486 T which we've seen before. 16 00:00:29,486 --> 00:00:32,206 So if I go to LoginController, shift command. 17 00:00:32,206 --> 00:00:33,505 T, Create a New Test. 18 00:00:33,505 --> 00:00:35,622 [No Audio] 19 00:00:35,622 --> 00:00:38,780 And we're just going to have this service method here. 20 00:00:38,780 --> 00:00:40,730 [No Audio] 21 00:00:40,730 --> 00:00:42,763 And let's put a setup method in as well. 22 00:00:42,763 --> 00:00:44,776 [No Audio] 23 00:00:44,776 --> 00:00:46,486 So now we're going to test this service method. 24 00:00:46,486 --> 00:00:50,528 Let's just put , prefix it with test, testService. 25 00:00:50,528 --> 00:00:53,036 So in order to test if we go 26 00:00:53,036 --> 00:00:55,114 back to the test class with shift command 27 00:00:55,114 --> 00:00:58,196 T, in order to test this LoginController we 28 00:00:58,196 --> 00:01:00,404 need to number one create an instance of it. 29 00:01:00,404 --> 00:01:03,250 And number two make sure that, that instance 30 00:01:03,250 --> 00:01:05,324 also has an AuthenticationService as well. 31 00:01:05,324 --> 00:01:08,171 So this AuthenticationService which is here, we're not 32 00:01:08,171 --> 00:01:10,700 going to set the real AuthenticationService. Instead 33 00:01:10,700 --> 00:01:12,958 we're going to set the mock AuthenticationService. 34 00:01:12,958 --> 00:01:15,258 So therefore going back to our test, 35 00:01:15,258 --> 00:01:17,204 [No Audio] 36 00:01:17,204 --> 00:01:18,587 we want to have two fields, 37 00:01:18,587 --> 00:01:22,078 [No Audio] 38 00:01:22,078 --> 00:01:23,910 the controller itself 39 00:01:23,910 --> 00:01:25,404 which is the system and the test. 40 00:01:25,404 --> 00:01:27,130 That's the thing we're actually testing. 41 00:01:27,130 --> 00:01:30,250 [No Audio] 42 00:01:30,250 --> 00:01:35,296 And we also want to have the AuthenticationService. 43 00:01:35,296 --> 00:01:37,722 I just call it service now. 44 00:01:37,722 --> 00:01:40,374 And this is going to be a mock. 45 00:01:40,374 --> 00:01:43,524 So we're going to set these up in the setup method. 46 00:01:43,524 --> 00:01:47,291 So this.controller = new 47 00:01:47,291 --> 00:01:49,374 logincontroller 48 00:01:49,374 --> 00:01:51,116 [No Audio] 49 00:01:51,116 --> 00:01:54,166 this.service= Mockito 50 00:01:54,166 --> 00:01:56,290 [No Audio] 51 00:01:56,290 --> 00:01:57,256 .mock 52 00:01:57,256 --> 00:02:00,306 [No Audio] 53 00:02:00,306 --> 00:02:02,863 AuthenticationService. That's great. That means 54 00:02:02,863 --> 00:02:06,463 that every time we add a test method to this class by 55 00:02:06,463 --> 00:02:09,596 using the @test annotation on the method, we're going 56 00:02:09,596 --> 00:02:13,184 to get a new brand new LoginController and a brand new 57 00:02:13,184 --> 00:02:16,483 mock to assign to the LoginController which we can 58 00:02:16,483 --> 00:02:18,983 set up and code to act in the way we want. 59 00:02:18,983 --> 00:02:20,386 So we're still going to do this assignment. 60 00:02:20,386 --> 00:02:22,184 So let's do that now. So to do this let's go into 61 00:02:22,184 --> 00:02:27,050 LoginController and let's add a constructor 62 00:02:27,050 --> 00:02:29,550 which takes the AuthenticationService 63 00:02:29,550 --> 00:02:33,417 So public LoginController AuthenticationService. 64 00:02:33,417 --> 00:02:36,930 [No Audio] 65 00:02:36,930 --> 00:02:40,683 Then we can do this. .authenticationService 66 00:02:40,683 --> 00:02:42,633 = authenticationService. 67 00:02:42,633 --> 00:02:44,623 [No Audio] 68 00:02:44,623 --> 00:02:48,374 So now we should be able to 69 00:02:48,374 --> 00:02:50,940 just create the mock before the controller. 70 00:02:50,940 --> 00:02:53,770 [No Audio] 71 00:02:53,770 --> 00:02:55,686 Now this is good. It means the LoginController 72 00:02:55,686 --> 00:02:58,961 has been set up with a mock AuthenticationService. 73 00:02:58,961 --> 00:03:01,264 Now you might be thinking, well, we could just 74 00:03:01,264 --> 00:03:07,661 as easily take this here, delete that and just 75 00:03:07,661 --> 00:03:11,411 pass it into the constructor and forget about this. 76 00:03:11,411 --> 00:03:13,576 Well yeah, but if we did that, of course we 77 00:03:13,576 --> 00:03:15,542 wouldn't then be able to access the mock to be 78 00:03:15,556 --> 00:03:17,572 able to set it up to act that we wanted 79 00:03:17,572 --> 00:03:20,544 to act inside each individual test method. 80 00:03:20,544 --> 00:03:21,602 So that's why we need it in 81 00:03:21,616 --> 00:03:24,483 a separate member reference, on the controller. 82 00:03:24,483 --> 00:03:28,866 So let's put that back and then we're ready to go. 83 00:03:28,866 --> 00:03:32,884 Just to prove this, if I set a breakpoint here and 84 00:03:32,884 --> 00:03:37,216 then if I go to Debug testService, I expect that 85 00:03:37,216 --> 00:03:40,399 I've got that test fixture set up correctly. Before 86 00:03:40,399 --> 00:03:45,496 that quickly I'll just set it to JDK7. Come to here. 87 00:03:45,496 --> 00:03:46,437 Preferences 88 00:03:46,437 --> 00:03:55,620 [No Audio] 89 00:03:55,620 --> 00:03:59,084 Java Compiler Target bytecode version and just 90 00:03:59,084 --> 00:04:04,346 change this to 7, then rerun with controler. 91 00:04:04,346 --> 00:04:08,422 Sorry, redebug with controld, then 92 00:04:08,436 --> 00:04:11,219 we hit the Breakpoint. So if we're looking now, this is 93 00:04:11,219 --> 00:04:15,035 the instance of our LoginController test. And inside 94 00:04:15,035 --> 00:04:18,235 here we expect to see the LoginController itself 95 00:04:18,235 --> 00:04:22,483 plus the service, which is set on that controller. 96 00:04:22,483 --> 00:04:23,486 Just double check that we've 97 00:04:23,498 --> 00:04:24,803 got the login controller here. 98 00:04:24,803 --> 00:04:27,204 You can see we've got the service also, which 99 00:04:27,204 --> 00:04:30,528 is a mock, and inside the controller we expect 100 00:04:30,528 --> 00:04:32,376 that mock is assigned, and you can see here 101 00:04:32,376 --> 00:04:35,120 it's assigned to the AuthenticationService. 102 00:04:35,120 --> 00:04:37,849 That's good. So let's stop that, 103 00:04:37,849 --> 00:04:39,690 get rid of that. 104 00:04:39,690 --> 00:04:46,973 So remember, we have arrange, act and assert. 105 00:04:46,973 --> 00:04:50,697 So now arrange, this is where we have an opportunity 106 00:04:50,697 --> 00:04:54,220 to set up our mock, to set it up as we want it to act. 107 00:04:54,220 --> 00:04:56,919 So for example, I can do this.service, 108 00:04:56,919 --> 00:04:59,461 [No Audio] 109 00:04:59,461 --> 00:05:02,477 I can do Mockito.when 110 00:05:02,477 --> 00:05:04,469 [No Audio] 111 00:05:04,469 --> 00:05:06,118 this is a static method on Mockito, 112 00:05:06,118 --> 00:05:08,878 which enables us to plug in behavior to this mock. 113 00:05:08,878 --> 00:05:13,894 Say if we just do an on demand static import for that, 114 00:05:13,894 --> 00:05:17,548 that should be the whole Mockito library, which we 115 00:05:17,548 --> 00:05:21,956 want. So if we just do Mockito.*, then we should 116 00:05:21,956 --> 00:05:25,788 have access to all of these methods here basically. 117 00:05:25,788 --> 00:05:29,398 And the ones we're really after, are the mock method. 118 00:05:29,398 --> 00:05:32,528 So we can take that away because it's a static import 119 00:05:32,528 --> 00:05:37,190 now, the when method and the then method. 120 00:05:37,190 --> 00:05:39,296 So how when and then works is basically we 121 00:05:39,296 --> 00:05:41,176 say when and then we pass in the mock 122 00:05:41,176 --> 00:05:45,856 and then invoke the actual method on the object 123 00:05:45,856 --> 00:05:48,150 and we're just going to say any string. 124 00:05:48,150 --> 00:05:50,150 [No Audio] 125 00:05:50,150 --> 00:05:53,936 So whenever any string is passed for 126 00:05:53,936 --> 00:05:55,318 the username and any string is passed 127 00:05:55,318 --> 00:05:58,483 for the password, regardless of what's passed. 128 00:05:58,483 --> 00:06:01,414 Because now this isn't a data test, we're not testing 129 00:06:01,414 --> 00:06:04,136 a function as we've seen before, what we're testing now 130 00:06:04,136 --> 00:06:06,219 is actual behavior, which is a difference, 131 00:06:06,219 --> 00:06:08,969 [No Audio] 132 00:06:08,969 --> 00:06:10,100 say .thenReturn 133 00:06:10,100 --> 00:06:12,216 [No Audio] 134 00:06:12,216 --> 00:06:14,654 and it wants us to return something of type boolean. 135 00:06:14,654 --> 00:06:16,194 So we say .theReturn true. 136 00:06:16,194 --> 00:06:18,026 So what we're doing here basically is we're 137 00:06:18,026 --> 00:06:19,692 setting up the mock to act as if 138 00:06:19,692 --> 00:06:21,948 the authenticate method always returns true. 139 00:06:21,948 --> 00:06:23,662 So let's go back to the authentication method, in 140 00:06:23,662 --> 00:06:27,545 AuthenticationService, this method here usually 141 00:06:27,545 --> 00:06:31,495 delegates to the user repository, finds the user by 142 00:06:31,495 --> 00:06:35,262 the username, gets a user object, then looks the 143 00:06:35,262 --> 00:06:36,870 password on the object and see if it equals the 144 00:06:36,870 --> 00:06:39,311 password. That's what it usually does. 145 00:06:39,311 --> 00:06:41,360 However, what we're doing with the mock 146 00:06:41,360 --> 00:06:45,444 is we're basically effectively commenting all that 147 00:06:45,444 --> 00:06:48,800 out and replacing with the custom implementation. 148 00:06:48,800 --> 00:06:50,990 And the custom implementation 149 00:06:50,990 --> 00:06:54,708 effectively is returned true. 150 00:06:54,708 --> 00:06:56,424 I'll do that now. 151 00:06:56,424 --> 00:06:58,224 That was just for illustration purposes, but 152 00:06:58,224 --> 00:06:59,640 yeah, you get what I mean. 153 00:06:59,640 --> 00:07:03,010 [No Audio] 154 00:07:03,010 --> 00:07:06,438 So to go back to the LoginController test, we're 155 00:07:06,438 --> 00:07:09,537 saying whenever we call authenticate with any string 156 00:07:09,537 --> 00:07:11,987 for username, any string for password, then it's 157 00:07:11,987 --> 00:07:14,371 going to return true, and this sets us up in a happy 158 00:07:14,371 --> 00:07:17,070 path scenario. We're really testing the happy path here 159 00:07:17,070 --> 00:07:18,916 where the user is going to be logged in. 160 00:07:18,916 --> 00:07:20,776 Okay, so what happens when the user is going to 161 00:07:20,776 --> 00:07:23,020 be logged in, from a production code point of view? 162 00:07:23,020 --> 00:07:24,519 Well, let's look back at the LoginController 163 00:07:24,519 --> 00:07:26,592 and look at the logic there. 164 00:07:26,592 --> 00:07:32,625 If this method here, if AuthenticationService.authenticate 165 00:07:32,625 --> 00:07:34,074 passing in the username password. 166 00:07:34,074 --> 00:07:38,956 If it does equal true alright, then we're going 167 00:07:38,956 --> 00:07:41,980 to return the path to the home page. 168 00:07:41,980 --> 00:07:44,152 And if it's not true, we return 169 00:07:44,152 --> 00:07:45,160 the path to the login page, 170 00:07:45,160 --> 00:07:46,696 but we're working with the fact that it 171 00:07:46,696 --> 00:07:48,256 is true now because that's how we've set 172 00:07:48,256 --> 00:07:50,576 up our mock for this specific test. 173 00:07:50,576 --> 00:07:53,104 So when it is true, we expect that the 174 00:07:53,104 --> 00:07:55,696 user will be effectively sent to the home page. 175 00:07:55,696 --> 00:07:57,898 Okay, so how do we communicate like the test? 176 00:07:57,898 --> 00:08:00,414 Jump back to the test, shift command 177 00:08:00,414 --> 00:08:02,578 T again log and control the test. 178 00:08:02,578 --> 00:08:04,880 We basically do the action. 179 00:08:04,880 --> 00:08:07,890 So this is where we're going to call the controller. 180 00:08:07,890 --> 00:08:09,402 We can prefix it with this dot 181 00:08:09,402 --> 00:08:11,662 also, but we don't necessarily have to. 182 00:08:11,662 --> 00:08:14,074 In fact, I prefer not to. 183 00:08:14,074 --> 00:08:16,207 So we'll also take it out from here as well. 184 00:08:16,207 --> 00:08:18,213 [No Audio] 185 00:08:18,213 --> 00:08:22,756 The action now is controller.service and 186 00:08:22,756 --> 00:08:24,380 we can pass in any old thing now it doesn't really 187 00:08:24,380 --> 00:08:29,374 matter, tom password123. 188 00:08:29,374 --> 00:08:30,806 But the key point here, of course is that 189 00:08:30,808 --> 00:08:33,784 we get back the view name or viewPath. 190 00:08:33,784 --> 00:08:35,986 Let's call it viewPath. 191 00:08:35,986 --> 00:08:38,754 So in this case when we get the viewPath 192 00:08:38,754 --> 00:08:41,631 back we expect now that it's equal to /home 193 00:08:41,631 --> 00:08:44,356 so we can do the Assert. 194 00:08:44,356 --> 00:08:48,313 [No Audio] 195 00:08:48,313 --> 00:08:50,049 assertNotNull(viewPath). 196 00:08:50,049 --> 00:08:51,909 We don't want to get back a null viewPath. 197 00:08:51,909 --> 00:08:53,078 That will be wrong. 198 00:08:53,078 --> 00:08:54,794 Next, Assert. 199 00:08:54,794 --> 00:08:57,252 [No Audio] 200 00:08:57,252 --> 00:09:00,410 assertEquals expect and actual. 201 00:09:00,410 --> 00:09:07,852 So we expected /home and the actual is viewPath. 202 00:09:07,852 --> 00:09:10,119 So now if we run this 203 00:09:10,119 --> 00:09:15,667 [No Audio] 204 00:09:15,667 --> 00:09:17,625 we can see that that test has passed and we probably 205 00:09:17,625 --> 00:09:20,040 want to give it a more descriptive test name as well. 206 00:09:20,040 --> 00:09:24,711 For example, testService_validUsername 207 00:09:24,711 --> 00:09:26,899 [No Audio] 208 00:09:26,899 --> 00:09:27,698 and password 209 00:09:27,698 --> 00:09:30,449 [No Audio] 210 00:09:30,449 --> 00:09:32,788 logs in user, for example. That's nice. 211 00:09:32,788 --> 00:09:34,012 It means we've basically got a test 212 00:09:34,012 --> 00:09:36,436 method now which is named descriptively to 213 00:09:36,436 --> 00:09:38,598 describe what the test is actually testing. 214 00:09:38,598 --> 00:09:41,042 So that's nice. We've now seen first hand how we can 215 00:09:41,056 --> 00:09:43,458 use Mockito to test the LoginController. 216 00:09:43,458 --> 00:09:45,270 Let's jump in now and we'll do another one and we'll 217 00:09:45,270 --> 00:09:48,327 explore how to test the AuthenticationService .