1 00:00:06,570 --> 00:00:08,520 - Client-side web applications, 2 00:00:08,520 --> 00:00:11,460 typically called REST services on the server, 3 00:00:11,460 --> 00:00:13,893 to get and modify data from the server. 4 00:00:15,000 --> 00:00:17,580 So the code that invokes the REST service 5 00:00:17,580 --> 00:00:20,430 is typically asynchronous on the background thread, 6 00:00:20,430 --> 00:00:21,960 because it might take a few seconds 7 00:00:21,960 --> 00:00:23,910 for the REST response to come back. 8 00:00:23,910 --> 00:00:26,160 So when you invoke the REST service, 9 00:00:26,160 --> 00:00:29,130 you typically get back a Promise object immediately, 10 00:00:29,130 --> 00:00:31,800 but that Promise object is a pending result. 11 00:00:31,800 --> 00:00:34,560 You won't actually get a value inside that Promise object 12 00:00:34,560 --> 00:00:36,720 until the REST service has completed. 13 00:00:36,720 --> 00:00:38,700 So the Promise object, basically, 14 00:00:38,700 --> 00:00:41,790 will either resolve eventually with the actual result 15 00:00:41,790 --> 00:00:43,770 or it'll reject with an error. 16 00:00:43,770 --> 00:00:45,930 And what you have to do somehow in your tests 17 00:00:45,930 --> 00:00:47,220 is deal with that. 18 00:00:47,220 --> 00:00:49,020 How can I take the Promise object, 19 00:00:49,020 --> 00:00:50,880 and either take the result 20 00:00:50,880 --> 00:00:53,040 if it's been resolved successfully 21 00:00:53,040 --> 00:00:56,880 or handle the error if it was rejected? 22 00:00:56,880 --> 00:00:58,950 So we're gonna see how to do that in this section. 23 00:00:58,950 --> 00:01:01,140 We're going to see how to mock functions 24 00:01:01,140 --> 00:01:02,460 that return a Promise. 25 00:01:02,460 --> 00:01:05,580 The last thing that you want to do when you are unit-testing 26 00:01:05,580 --> 00:01:08,040 is to actually call the REST service, 27 00:01:08,040 --> 00:01:09,570 because it's gonna be too slow. 28 00:01:09,570 --> 00:01:11,190 You don't want to wait five seconds 29 00:01:11,190 --> 00:01:12,660 for the Promise to resolve. 30 00:01:12,660 --> 00:01:14,280 You can mock that instead, 31 00:01:14,280 --> 00:01:16,350 and you can mock whether the Promise 32 00:01:16,350 --> 00:01:17,883 is rejected or resolved. 33 00:01:19,710 --> 00:01:22,590 So imagine this hypothetical situation. 34 00:01:22,590 --> 00:01:24,570 I've got someFunction and someModule 35 00:01:25,430 --> 00:01:27,450 and it returns a Promise object. 36 00:01:27,450 --> 00:01:29,280 In other words, here is a Promise object 37 00:01:29,280 --> 00:01:32,250 which will eventually either be resolved with a result 38 00:01:32,250 --> 00:01:33,693 or rejected with an error. 39 00:01:34,590 --> 00:01:38,310 So what we could do is we could mock this module. 40 00:01:38,310 --> 00:01:41,730 We could import the module, which I've imported someModule, 41 00:01:41,730 --> 00:01:43,050 I've called it m. 42 00:01:43,050 --> 00:01:45,180 And then I can create mocks 43 00:01:45,180 --> 00:01:47,280 for all the functions in that module. 44 00:01:47,280 --> 00:01:48,630 So I've mocked someFunction 45 00:01:49,860 --> 00:01:53,040 and then I can mock the return value. 46 00:01:53,040 --> 00:01:55,920 When you have a function that you mock like this, 47 00:01:55,920 --> 00:01:57,960 remember when you call jest.mock, 48 00:01:57,960 --> 00:01:59,940 it'll create a mock of all the functions. 49 00:01:59,940 --> 00:02:03,690 And by default, the mock will return undefined. 50 00:02:03,690 --> 00:02:05,880 So what you can do is you can say this module, 51 00:02:05,880 --> 00:02:07,500 which I've just imported, 52 00:02:07,500 --> 00:02:09,500 that has a function called someFunction. 53 00:02:10,945 --> 00:02:13,200 I've mocked that function here. 54 00:02:13,200 --> 00:02:15,570 What I'm gonna do is I'm gonna mock its return value. 55 00:02:15,570 --> 00:02:18,960 I'm going to say that that function when it returns, 56 00:02:18,960 --> 00:02:20,250 it'll return a Promise, 57 00:02:20,250 --> 00:02:22,410 I'm going to mock that that Promise 58 00:02:22,410 --> 00:02:25,260 will resolve with this result. 59 00:02:25,260 --> 00:02:26,940 So you're not just mocking the fact 60 00:02:26,940 --> 00:02:28,200 that it returns a Promise. 61 00:02:28,200 --> 00:02:29,940 You're mocking the fact that the Promise object 62 00:02:29,940 --> 00:02:33,660 actually succeeds and here is the eventual result 63 00:02:33,660 --> 00:02:35,940 of that Promise, as if it's the real data 64 00:02:35,940 --> 00:02:38,130 that's come back from the REST service. 65 00:02:38,130 --> 00:02:42,840 And also, I can say, this function that returns a Promise 66 00:02:42,840 --> 00:02:45,240 or that when I mock it doesn't return anything, 67 00:02:45,240 --> 00:02:49,060 but I can mock it to return a Promise that is rejected. 68 00:02:49,060 --> 00:02:52,530 As if we'd called the real function 69 00:02:52,530 --> 00:02:56,220 that return a Promise and that Promise had rejected, 70 00:02:56,220 --> 00:02:58,230 that's what we're mocking here. 71 00:02:58,230 --> 00:03:01,440 Mock the fact that the function would've been revoked, 72 00:03:01,440 --> 00:03:03,960 returned the Promise and that Promise was rejected, 73 00:03:03,960 --> 00:03:05,210 basically, with an error. 74 00:03:07,140 --> 00:03:09,600 Well, let's have a look at a concrete example of that 75 00:03:09,600 --> 00:03:12,630 to see how it all hands together in practical terms. 76 00:03:12,630 --> 00:03:14,670 So have a look, if you want to, again 77 00:03:14,670 --> 00:03:15,870 if you wanna follow along, 78 00:03:15,870 --> 00:03:17,940 go into the MOCKING_PROMISES folder. 79 00:03:17,940 --> 00:03:20,030 I've got several code files in there 80 00:03:20,030 --> 00:03:22,080 if you wanna take a look. 81 00:03:22,080 --> 00:03:25,470 So I have two main Java files. 82 00:03:25,470 --> 00:03:26,460 I've got a Java file 83 00:03:26,460 --> 00:03:29,820 which encapsulates calls to a REST service. 84 00:03:29,820 --> 00:03:31,260 We'll have a look at that first. 85 00:03:31,260 --> 00:03:33,600 And then I've got another JavaScript file 86 00:03:33,600 --> 00:03:35,460 which is like in front of it. 87 00:03:35,460 --> 00:03:39,900 So this is my logic and it calls the REST client 88 00:03:39,900 --> 00:03:42,150 to interact with the backend. 89 00:03:42,150 --> 00:03:45,180 This will have functions that return Promises. 90 00:03:45,180 --> 00:03:46,980 I will grab those Promises here, 91 00:03:46,980 --> 00:03:49,980 take the results and do some work on them. 92 00:03:49,980 --> 00:03:51,240 Once we've seen how that works, 93 00:03:51,240 --> 00:03:53,550 then we'll see how we can write tests 94 00:03:53,550 --> 00:03:55,590 to mock those Promises. 95 00:03:55,590 --> 00:03:57,600 So we'll take this step by step. 96 00:03:57,600 --> 00:04:00,300 So first of all, we'll have a look at the REST client. 97 00:04:01,140 --> 00:04:02,970 So here's my REST client. 98 00:04:02,970 --> 00:04:06,150 So this is the picture that we've got. 99 00:04:06,150 --> 00:04:09,840 At the backend, there is a REST service. 100 00:04:09,840 --> 00:04:13,110 So that's running, maybe's implemented in Java Spring Boot 101 00:04:13,110 --> 00:04:14,580 or Web API. 102 00:04:14,580 --> 00:04:16,800 That's my REST service at the backend. 103 00:04:16,800 --> 00:04:21,510 And this API on the client has functions 104 00:04:21,510 --> 00:04:24,810 that basically invoke that RETS service at the backend. 105 00:04:24,810 --> 00:04:28,470 So it's a hypothetical online retail store 106 00:04:28,470 --> 00:04:30,990 where we can get information about products. 107 00:04:30,990 --> 00:04:33,240 So I've got a function here, get all products. 108 00:04:33,240 --> 00:04:35,520 This is in my REST client API. 109 00:04:35,520 --> 00:04:36,993 So I'm gonna draw a box here. 110 00:04:38,400 --> 00:04:42,210 This box here represents my REST client. 111 00:04:42,210 --> 00:04:44,550 I'm gonna draw this picture a few times 112 00:04:44,550 --> 00:04:47,520 in the next few minutes as we progress through 113 00:04:47,520 --> 00:04:49,800 just so you can see the progression. 114 00:04:49,800 --> 00:04:52,623 So I've got in here a function called getAllProducts, 115 00:04:53,559 --> 00:04:54,392 getAllProducts. 116 00:04:54,392 --> 00:04:55,840 So I'll draw that function here. 117 00:04:58,465 --> 00:05:01,860 I just call it, getAll just to give myself a bit more space, 118 00:05:01,860 --> 00:05:02,850 getAll. 119 00:05:02,850 --> 00:05:04,860 So when I call that function, 120 00:05:04,860 --> 00:05:08,878 what this function does is uses axios. 121 00:05:08,878 --> 00:05:10,710 So axios is a standard, 122 00:05:10,710 --> 00:05:15,090 fairly useful library for calling REST services. 123 00:05:15,090 --> 00:05:18,600 So you can say, I wanna make a getRequest to a URL. 124 00:05:18,600 --> 00:05:21,690 I've got a hypothetical URL up here. 125 00:05:21,690 --> 00:05:24,690 And the idea is that it returns me a collection of products. 126 00:05:26,130 --> 00:05:30,540 So the thing is the get function returns a Promise 127 00:05:30,540 --> 00:05:32,410 and it will take a while to complete it. 128 00:05:32,410 --> 00:05:36,700 It'll take a while for that Promise object to be returned 129 00:05:38,070 --> 00:05:39,510 from the REST service. 130 00:05:39,510 --> 00:05:41,970 When that has been returned, 131 00:05:41,970 --> 00:05:46,020 the response you get here is the entire HTTP response body 132 00:05:46,020 --> 00:05:49,650 back from the server, including headers, status code, 133 00:05:49,650 --> 00:05:51,300 and the body itself. 134 00:05:51,300 --> 00:05:53,280 So when that data has been returned, 135 00:05:53,280 --> 00:05:55,950 what we then do is to take the HTTP response 136 00:05:55,950 --> 00:05:58,530 and just get the HTTP body 137 00:05:58,530 --> 00:06:00,930 which is the actual data that we want. 138 00:06:00,930 --> 00:06:04,320 So if you follow this through, 139 00:06:04,320 --> 00:06:06,900 if this function returns a Promise 140 00:06:06,900 --> 00:06:09,900 then function also returns a Promise. 141 00:06:09,900 --> 00:06:13,110 So the net result is what I call getAllProducts 142 00:06:13,110 --> 00:06:14,730 for my other code. 143 00:06:14,730 --> 00:06:16,380 We'll see that in a minute. 144 00:06:16,380 --> 00:06:19,083 That will return a Promise. 145 00:06:20,850 --> 00:06:25,200 So this code here is going to return a Promise 146 00:06:25,200 --> 00:06:28,560 that will eventually contain all products. 147 00:06:28,560 --> 00:06:29,700 And then a similar function here, 148 00:06:29,700 --> 00:06:32,370 which I won't go into, but it's the same idea. 149 00:06:32,370 --> 00:06:35,070 Instead of getting all products, similar idea, 150 00:06:35,070 --> 00:06:38,250 but this function gets the product with a particular ID. 151 00:06:38,250 --> 00:06:43,250 So it issues a getRequest, products slash ID like one. 152 00:06:43,560 --> 00:06:45,900 And hopefully, that will return the data 153 00:06:45,900 --> 00:06:48,120 for just one product 154 00:06:48,120 --> 00:06:50,910 which we then return back via a Promise. 155 00:06:50,910 --> 00:06:53,850 So this REST client, it provides functions 156 00:06:53,850 --> 00:06:55,410 which return a Promise 157 00:06:55,410 --> 00:06:59,040 and I'm going to use that API in my higher level code. 158 00:06:59,040 --> 00:07:00,600 That's the next function 159 00:07:00,600 --> 00:07:03,240 or the next file we're going to look at. 160 00:07:03,240 --> 00:07:06,150 So note this here that both of those functions 161 00:07:06,150 --> 00:07:10,140 return a Promise and now we're going to use it here. 162 00:07:10,140 --> 00:07:14,283 So I'm going to just draw the backend again. 163 00:07:15,150 --> 00:07:18,180 This is my REST client that we just looked at. 164 00:07:18,180 --> 00:07:21,063 So draw that backend REST client. 165 00:07:22,260 --> 00:07:24,760 And then it had two functions, getAll and getById. 166 00:07:26,880 --> 00:07:28,280 We just imagine those there, 167 00:07:29,940 --> 00:07:33,903 which call into my REST service, which is a blob like that. 168 00:07:35,070 --> 00:07:36,450 So we've seen that already. 169 00:07:36,450 --> 00:07:37,650 And what we're gonna do now is we're going to look 170 00:07:37,650 --> 00:07:42,030 at a higher level code that sits in front of it and uses it. 171 00:07:42,030 --> 00:07:44,160 And this is my operations.js. 172 00:07:44,160 --> 00:07:47,100 So operations, my higher level code 173 00:07:47,100 --> 00:07:50,250 that uses the REST client as a service provider, 174 00:07:50,250 --> 00:07:52,950 basically, operations.js. 175 00:07:52,950 --> 00:07:55,800 So what I'm gonna do is I'm gonna have two semantic methods, 176 00:07:55,800 --> 00:07:58,320 one that will return the total stock count. 177 00:07:58,320 --> 00:08:02,670 So imagine I've got various products in my catalog. 178 00:08:02,670 --> 00:08:05,130 I've got four of one product, 179 00:08:05,130 --> 00:08:06,630 three of another product, 180 00:08:06,630 --> 00:08:08,310 and five of another product. 181 00:08:08,310 --> 00:08:10,020 What this function's meant to do 182 00:08:10,020 --> 00:08:12,600 is to return the total number of products 183 00:08:12,600 --> 00:08:13,590 I've got all together. 184 00:08:13,590 --> 00:08:15,450 So if I've got five of that product 185 00:08:15,450 --> 00:08:18,120 and three of that product and four of that product, 186 00:08:18,120 --> 00:08:21,450 that's gonna be five plus three plus four, that'd be 12. 187 00:08:21,450 --> 00:08:23,550 That's what this function is hoping to do. 188 00:08:24,510 --> 00:08:25,950 So if we just have a look then. 189 00:08:25,950 --> 00:08:28,650 We are going to call the getAllProducts method. 190 00:08:28,650 --> 00:08:31,350 So this here, I'll call this, 191 00:08:31,350 --> 00:08:34,099 this is my getStockCount function, 192 00:08:34,099 --> 00:08:34,932 getStockCount. 193 00:08:34,932 --> 00:08:37,440 Hopefully that you can read my writing there. 194 00:08:37,440 --> 00:08:39,270 That's my best writing. 195 00:08:39,270 --> 00:08:43,380 So when I call the getStockCount method, 196 00:08:43,380 --> 00:08:45,690 the first thing it has to do on my REST client, 197 00:08:45,690 --> 00:08:47,190 it calls getAllProducts. 198 00:08:47,190 --> 00:08:48,600 So the first thing it does 199 00:08:48,600 --> 00:08:51,930 is to call getAllProducts like that. 200 00:08:51,930 --> 00:08:53,130 It returns immediately. 201 00:08:53,130 --> 00:08:56,013 That function returns immediately with a Promise object. 202 00:08:57,480 --> 00:09:00,240 That Promise object will eventually contain 203 00:09:00,240 --> 00:09:03,330 a bunch of products, eventually. 204 00:09:03,330 --> 00:09:05,410 So what I say is take that Promise object 205 00:09:07,201 --> 00:09:10,290 or when it has resolved, assuming that it succeeds, 206 00:09:10,290 --> 00:09:14,340 when it is resolved then this parameter here 207 00:09:14,340 --> 00:09:16,890 will be the products, the result, basically. 208 00:09:16,890 --> 00:09:19,923 The products array inside the Promise. 209 00:09:20,880 --> 00:09:22,770 The result in the Promise object, 210 00:09:22,770 --> 00:09:25,950 that is what's going to that's that. 211 00:09:25,950 --> 00:09:27,903 Basically, that is this. 212 00:09:29,310 --> 00:09:31,170 So what we then do, I've got some code here, 213 00:09:31,170 --> 00:09:32,820 which I was quite pleased 214 00:09:32,820 --> 00:09:34,230 when I figured out how to make this code. 215 00:09:34,230 --> 00:09:36,360 It takes that array of products. 216 00:09:36,360 --> 00:09:39,030 Imagine that each product has a stock property. 217 00:09:39,030 --> 00:09:40,770 So it says, take that array of products. 218 00:09:40,770 --> 00:09:43,530 So that's my array of products here. 219 00:09:43,530 --> 00:09:47,910 And for each product, so P would be one product. 220 00:09:47,910 --> 00:09:49,360 Give me just the stock value. 221 00:09:50,310 --> 00:09:52,110 So maybe five is the first stock, 222 00:09:52,110 --> 00:09:55,290 three is the second stock and four is the third stock. 223 00:09:55,290 --> 00:09:57,750 So that just give me a bunch of stock numbers. 224 00:09:57,750 --> 00:09:59,940 And then I call the reduce function. 225 00:09:59,940 --> 00:10:01,470 If you haven't seen the reduce function before, 226 00:10:01,470 --> 00:10:03,420 it's very cool. 227 00:10:03,420 --> 00:10:07,140 What it does, it kind of takes two parameters 228 00:10:07,140 --> 00:10:09,270 and reduces them to one result. 229 00:10:09,270 --> 00:10:13,380 So the first parameter is like the ongoing total. 230 00:10:13,380 --> 00:10:16,470 This here is the initial value for that parameter 231 00:10:16,470 --> 00:10:18,510 just to bootstrap the process. 232 00:10:18,510 --> 00:10:22,773 This here is the initial value for that parameter. 233 00:10:24,240 --> 00:10:29,240 And next, that's basically the first value from our array. 234 00:10:29,730 --> 00:10:32,250 So from this array, which let's say that array cabinet 235 00:10:32,250 --> 00:10:37,170 contains stock numbers like five and three and four. 236 00:10:37,170 --> 00:10:38,040 That's a bit difficult to read 237 00:10:38,040 --> 00:10:39,270 but hopefully you get the idea. 238 00:10:39,270 --> 00:10:41,790 Next would be the first value from there. 239 00:10:41,790 --> 00:10:44,700 And what I do is I return the current total, 240 00:10:44,700 --> 00:10:47,880 which is zero plus the next value, 241 00:10:47,880 --> 00:10:51,690 and that gives me back the new aggregate total. 242 00:10:51,690 --> 00:10:56,490 So that would say zero plus five is five. 243 00:10:56,490 --> 00:10:59,310 What it then does, is it repeats the process it says. 244 00:10:59,310 --> 00:11:01,563 So that is the total so far. 245 00:11:02,760 --> 00:11:05,580 And then it takes the next value from there. 246 00:11:05,580 --> 00:11:09,123 And it passes in and it says five plus three, 247 00:11:10,440 --> 00:11:11,613 well, that'll be eight. 248 00:11:12,608 --> 00:11:14,910 So that's our new total, eight. 249 00:11:14,910 --> 00:11:16,530 And then that becomes the value 250 00:11:16,530 --> 00:11:19,110 for the next incarnation like that. 251 00:11:19,110 --> 00:11:21,090 And then it'll grab the next value from here 252 00:11:21,090 --> 00:11:21,923 and pass it in like that. 253 00:11:21,923 --> 00:11:23,220 So as you can see, what this is going to do? 254 00:11:23,220 --> 00:11:26,640 Basically, is it's going to take the stock of each product 255 00:11:26,640 --> 00:11:28,620 and then add it, add them together. 256 00:11:28,620 --> 00:11:30,780 It'll give me the total stock, 257 00:11:30,780 --> 00:11:34,350 assuming that the Promise was resolved successfully. 258 00:11:34,350 --> 00:11:36,210 'Cause what could have happened is the Promise 259 00:11:36,210 --> 00:11:38,280 could have actually been a rejection 260 00:11:38,280 --> 00:11:40,560 in which case I have a catch. 261 00:11:40,560 --> 00:11:42,510 And in this case, I just returned zero. 262 00:11:42,510 --> 00:11:44,550 If I can't call the REST service, 263 00:11:44,550 --> 00:11:47,250 then instead of returning a proper stock value, 264 00:11:47,250 --> 00:11:50,583 I just return zero as a suitable fallback. 265 00:11:52,290 --> 00:11:53,610 So hopefully that makes sense. 266 00:11:53,610 --> 00:11:55,860 Have a look at the code and, and have a play with it 267 00:11:55,860 --> 00:11:57,300 if you just wanna make sure. 268 00:11:57,300 --> 00:12:00,300 The code is all there in the demo pack, 269 00:12:00,300 --> 00:12:04,500 just go into the MOCKING_PROMISES folder 270 00:12:04,500 --> 00:12:07,170 and have a look at operations.js. 271 00:12:07,170 --> 00:12:09,670 And the code is there for you to have a play with. 272 00:12:10,980 --> 00:12:13,350 The second function is the similar kind of idea. 273 00:12:13,350 --> 00:12:14,880 Instead of just giving me the stock count 274 00:12:14,880 --> 00:12:17,040 like to say you have 12 products, 275 00:12:17,040 --> 00:12:18,870 it gives me the cumulative total 276 00:12:18,870 --> 00:12:20,280 of everything I've got in stock. 277 00:12:20,280 --> 00:12:23,580 So very similar process, get all the products. 278 00:12:23,580 --> 00:12:24,690 Once we've got the products, 279 00:12:24,690 --> 00:12:28,680 what it does then is it multiplies the price of one product 280 00:12:28,680 --> 00:12:30,810 multiply by the stock of that product. 281 00:12:30,810 --> 00:12:32,430 It's like a line count. 282 00:12:32,430 --> 00:12:35,100 That would give me a total value of one particular product, 283 00:12:35,100 --> 00:12:36,630 which I then add together. 284 00:12:36,630 --> 00:12:38,670 And it'll give me the cumulative stock value 285 00:12:38,670 --> 00:12:39,960 of everything I've got in stock. 286 00:12:39,960 --> 00:12:41,580 If you've got 10 of those product 287 00:12:41,580 --> 00:12:44,760 and it cost a hundred, that's worth a thousand. 288 00:12:44,760 --> 00:12:47,070 So these functions should actually work. 289 00:12:47,070 --> 00:12:49,500 What I wanna do though, is to test them. 290 00:12:49,500 --> 00:12:51,210 I want to test that this function 291 00:12:51,210 --> 00:12:53,520 does actually give me back the right response. 292 00:12:53,520 --> 00:12:55,680 And in order to do that, 293 00:12:55,680 --> 00:12:58,080 I'm gonna have to mock that function. 294 00:12:58,080 --> 00:13:00,150 I'm gonna have to mock that function 295 00:13:00,150 --> 00:13:02,640 so they did either mocks with a result. 296 00:13:02,640 --> 00:13:04,500 In other words, it resolves to a result 297 00:13:04,500 --> 00:13:08,040 or that I'm gonna mock the fact that it marks with an error 298 00:13:08,040 --> 00:13:09,960 that it rejects an error basically. 299 00:13:09,960 --> 00:13:11,913 So let's see the tests. 300 00:13:13,440 --> 00:13:16,200 So again, these tests are in the demo pack, 301 00:13:16,200 --> 00:13:17,820 if you wanna have a good look. 302 00:13:17,820 --> 00:13:20,673 So that's in operations.test.js. 303 00:13:21,690 --> 00:13:25,230 So I import my operations code 304 00:13:25,230 --> 00:13:28,140 and I import my REST client code. 305 00:13:28,140 --> 00:13:29,130 And then what I've done here, 306 00:13:29,130 --> 00:13:33,000 often when you are test and you create mock data, 307 00:13:33,000 --> 00:13:36,330 so I've set up a dummy products collection. 308 00:13:36,330 --> 00:13:39,090 While we're going skiing in a few days, we are very excited. 309 00:13:39,090 --> 00:13:41,460 And so I thought here's an example. 310 00:13:41,460 --> 00:13:43,740 A product, skis. 311 00:13:43,740 --> 00:13:46,560 A pair of skis cost 500 pounds. 312 00:13:46,560 --> 00:13:49,110 And there were 10 of those in stock. 313 00:13:49,110 --> 00:13:52,140 A pair of ski boots cost 200 pounds 314 00:13:52,140 --> 00:13:54,630 and I've got five of those in stock. 315 00:13:54,630 --> 00:13:55,980 Don't forget the goggles. 316 00:13:55,980 --> 00:13:57,690 You need to have goggles when you skiing. 317 00:13:57,690 --> 00:13:59,940 And they only cost a hundred pound, a bargain, 318 00:13:59,940 --> 00:14:01,953 and we've got three of those in stock. 319 00:14:02,850 --> 00:14:05,370 So that's fairly straightforward. 320 00:14:05,370 --> 00:14:08,480 Then what I do is I mock all the functions 321 00:14:08,480 --> 00:14:10,170 in the REST client module. 322 00:14:10,170 --> 00:14:13,140 In other words, I mock all of the functions in here. 323 00:14:13,140 --> 00:14:16,800 I mock that function and I mock that function. 324 00:14:16,800 --> 00:14:20,130 And if you remember, what happens when you mock functions, 325 00:14:20,130 --> 00:14:22,110 when you mock an entire module? 326 00:14:22,110 --> 00:14:24,720 It'll create a mock version of each function 327 00:14:24,720 --> 00:14:27,453 that becomes undefined by default. 328 00:14:28,860 --> 00:14:31,473 So that makes sense so far. 329 00:14:32,670 --> 00:14:34,770 So just to pick out a few points then. 330 00:14:34,770 --> 00:14:37,233 Import the REST client API module, 331 00:14:38,460 --> 00:14:41,880 mock all the functions in that model. 332 00:14:41,880 --> 00:14:45,450 So by default, all those functions return undefined 333 00:14:45,450 --> 00:14:49,530 according to the mock, but I'm going to go a step further 334 00:14:49,530 --> 00:14:52,080 and I'm gonna say, well, actually, you know what, 335 00:14:52,080 --> 00:14:54,990 for the getAllProducts function, 336 00:14:54,990 --> 00:14:57,090 undefined doesn't really cut it. 337 00:14:57,090 --> 00:15:00,510 I'm gonna mock that as if it returned successfully 338 00:15:00,510 --> 00:15:02,400 with the Promise, which resolved. 339 00:15:02,400 --> 00:15:03,750 So, like I said earlier, 340 00:15:03,750 --> 00:15:06,210 you're not just mocking the fact that it returns a Promise. 341 00:15:06,210 --> 00:15:07,590 You go in a step further 342 00:15:07,590 --> 00:15:10,350 and say it didn't return just a Promise, 343 00:15:10,350 --> 00:15:14,100 it returned a Promise that resolved with this result. 344 00:15:14,100 --> 00:15:15,900 So this is the ultimate result 345 00:15:15,900 --> 00:15:17,910 that came back from the REST service. 346 00:15:17,910 --> 00:15:19,770 This is what my mock is achieving. 347 00:15:19,770 --> 00:15:21,780 I'm saying that when I call that function, 348 00:15:21,780 --> 00:15:23,220 it's as if it return a Promise 349 00:15:23,220 --> 00:15:26,610 which resolved to return those products. 350 00:15:26,610 --> 00:15:28,680 As if those products came back from the REST service. 351 00:15:28,680 --> 00:15:31,050 Those are the products that will eventually be passed 352 00:15:31,050 --> 00:15:32,940 into my client code. 353 00:15:32,940 --> 00:15:34,020 So have a look at this. 354 00:15:34,020 --> 00:15:37,290 The test itself is actually the easiest part. 355 00:15:37,290 --> 00:15:39,480 When I call getStockCount, 356 00:15:39,480 --> 00:15:42,660 and remember, that's the rather complicated function 357 00:15:42,660 --> 00:15:44,430 that I explained just now. 358 00:15:44,430 --> 00:15:48,420 Let me give you a quick recap just to remind you. 359 00:15:48,420 --> 00:15:52,410 So I'm calling that function 360 00:15:52,410 --> 00:15:56,670 and that function calls, REST client getAllProducts. 361 00:15:56,670 --> 00:15:59,280 I've just mocked that function to resolve 362 00:15:59,280 --> 00:16:00,780 with a bunch of products. 363 00:16:00,780 --> 00:16:04,020 So basically I've mocked the fact it's going to resolve 364 00:16:04,020 --> 00:16:07,260 as opposed to reject with an array of three products, 365 00:16:07,260 --> 00:16:10,053 ski boots, skis, and goggles. 366 00:16:11,160 --> 00:16:13,590 And what's more? 367 00:16:13,590 --> 00:16:15,303 Those products that I mocked, 368 00:16:16,555 --> 00:16:21,147 I basically mocked this to return that product array. 369 00:16:24,270 --> 00:16:25,772 And if you do a bit of math here, 370 00:16:25,772 --> 00:16:28,620 if you add up the stock here, if you've got 10 of that item 371 00:16:28,620 --> 00:16:31,500 plus five plus three that's 18, isn't it? 372 00:16:31,500 --> 00:16:34,890 So what I'm expecting is that this algorithm, 373 00:16:34,890 --> 00:16:36,630 if it's implemented correctly, 374 00:16:36,630 --> 00:16:39,270 should actually give me back 18 375 00:16:39,270 --> 00:16:42,595 because according to the products that I've just pumped in, 376 00:16:42,595 --> 00:16:44,280 the stock total is 18. 377 00:16:44,280 --> 00:16:46,440 Often you do this when you're testing. 378 00:16:46,440 --> 00:16:49,230 You give us some test data, hard coded, 379 00:16:49,230 --> 00:16:51,480 and you work out what the answer should be 380 00:16:51,480 --> 00:16:52,830 if your code is correct. 381 00:16:52,830 --> 00:16:55,833 If my code is correct, the stock count should be 18. 382 00:16:57,390 --> 00:16:59,340 So here's my expectation. 383 00:16:59,340 --> 00:17:01,380 First of all, when I call that function, 384 00:17:01,380 --> 00:17:04,620 it should have called that function on the REST client. 385 00:17:04,620 --> 00:17:08,053 And also the result that I get back should be 18. 386 00:17:11,040 --> 00:17:12,150 So just some notes. 387 00:17:12,150 --> 00:17:13,863 We call the function under test. 388 00:17:15,270 --> 00:17:17,340 It calls getAllProducts. 389 00:17:17,340 --> 00:17:21,000 Verify that that was called and then check. 390 00:17:21,000 --> 00:17:23,400 And this really is a proper check here, check. 391 00:17:23,400 --> 00:17:26,160 When I was writing my demo code, I did actually rely on this 392 00:17:26,160 --> 00:17:28,560 to make sure I'd implemented my algorithm correctly. 393 00:17:28,560 --> 00:17:29,850 Make sure that the result we got back 394 00:17:29,850 --> 00:17:31,560 is actually the correct result. 395 00:17:31,560 --> 00:17:34,980 18 is the result we expect to get back. 396 00:17:34,980 --> 00:17:38,640 Given the data that we've passed in 10 plus five plus eight, 397 00:17:38,640 --> 00:17:40,980 that should add up to 18. 398 00:17:40,980 --> 00:17:41,813 That's the first test. 399 00:17:41,813 --> 00:17:44,130 The second test, very similar, 400 00:17:44,130 --> 00:17:46,920 but instead of testing the stock count, 401 00:17:46,920 --> 00:17:48,870 I'm testing the stock value. 402 00:17:48,870 --> 00:17:52,860 Similar idea, I call the getStockValue function. 403 00:17:52,860 --> 00:17:56,553 So in my code, I'm now calling this function. 404 00:17:57,450 --> 00:18:01,110 It invokes that and I've mocked that to resolve. 405 00:18:01,110 --> 00:18:03,240 I've mocked that to resolve with those products, 406 00:18:03,240 --> 00:18:06,000 skis, boots, goggles. 407 00:18:06,000 --> 00:18:08,673 So that data is kind of hard coded in my test. 408 00:18:09,660 --> 00:18:14,370 So verify that my function called getAllProducts 409 00:18:15,809 --> 00:18:17,850 while it should have done, shouldn't it? 410 00:18:17,850 --> 00:18:20,670 And then check the logic here to see what value 411 00:18:20,670 --> 00:18:23,610 did it actually return when it multiplied the price 412 00:18:23,610 --> 00:18:25,350 by the stock for all those products. 413 00:18:25,350 --> 00:18:27,060 What value did it give back? 414 00:18:27,060 --> 00:18:28,230 According to my maths, 415 00:18:28,230 --> 00:18:31,953 the value should have been 6,300. 416 00:18:32,910 --> 00:18:33,743 I think that's right. 417 00:18:33,743 --> 00:18:37,203 Let's go have a quick look in my test. 418 00:18:38,100 --> 00:18:43,100 I've got 500 pounds for each pair of skis 419 00:18:43,650 --> 00:18:44,910 and I've got 10 of them. 420 00:18:44,910 --> 00:18:46,353 That's 5,000 pound. 421 00:18:47,670 --> 00:18:50,640 200 pounds for a pair of boots and five of those. 422 00:18:50,640 --> 00:18:51,780 That's another thousand. 423 00:18:51,780 --> 00:18:56,340 So that's 5,000 plus 6,000 plus 300. 424 00:18:56,340 --> 00:18:58,230 So the total value of each line, 425 00:18:58,230 --> 00:19:01,860 the total value should be 6,300, 426 00:19:01,860 --> 00:19:03,450 shouldn't it? 427 00:19:03,450 --> 00:19:04,530 Yes. 428 00:19:04,530 --> 00:19:06,030 So just to verify then, 429 00:19:06,030 --> 00:19:07,800 I call the function-under-test. 430 00:19:07,800 --> 00:19:12,800 It should have invoked this API, which I told it to resolve 431 00:19:13,140 --> 00:19:18,140 with a bunch of products whose results should give me 6,300. 432 00:19:19,980 --> 00:19:22,080 I ran this test and it does actually work. 433 00:19:23,160 --> 00:19:25,650 The final outcome, as well as testing 434 00:19:25,650 --> 00:19:27,420 for Promises that resolve, 435 00:19:27,420 --> 00:19:29,880 you've really got to test for Promises that reject. 436 00:19:29,880 --> 00:19:32,130 So that's what I've done in my final test. 437 00:19:32,130 --> 00:19:36,030 I basically mock, in my mock module. 438 00:19:36,030 --> 00:19:37,200 Just remind you again, 439 00:19:37,200 --> 00:19:40,080 just so that you haven't lost sight of this. 440 00:19:40,080 --> 00:19:43,410 Remember the first thing I did in my test 441 00:19:43,410 --> 00:19:45,660 was to mock the entire module. 442 00:19:45,660 --> 00:19:46,950 When you mock the module, 443 00:19:46,950 --> 00:19:51,120 every function in there is mocked to return undefined. 444 00:19:51,120 --> 00:19:54,030 So initially I mocked the getAllProducts function 445 00:19:54,030 --> 00:19:56,220 to resolve successfully. 446 00:19:56,220 --> 00:19:59,460 What I'm doing in this test is I'm saying I wanted to mock 447 00:19:59,460 --> 00:20:00,600 with a rejected value. 448 00:20:00,600 --> 00:20:04,080 So in other words, it's like a Promise that rejects 449 00:20:04,080 --> 00:20:05,283 with this error message. 450 00:20:06,150 --> 00:20:10,563 So when I call getStockCount what should happen is, 451 00:20:12,090 --> 00:20:13,440 when I say getStockCount, 452 00:20:13,440 --> 00:20:17,790 it should go into the catch block here and return zero. 453 00:20:17,790 --> 00:20:21,003 So verify that the result we got back is zero. 454 00:20:23,996 --> 00:20:26,796 When I call my getStockValue, the result should be zero. 455 00:20:28,470 --> 00:20:31,650 Because when the Promise rejects, 456 00:20:31,650 --> 00:20:35,253 it returns zero as the fallback value really. 457 00:20:36,150 --> 00:20:38,130 Well, that was quite a lot of hard work. 458 00:20:38,130 --> 00:20:39,123 So just a note, 459 00:20:40,020 --> 00:20:43,350 I specify that I want my REST called to fail. 460 00:20:43,350 --> 00:20:45,390 Basically with that error. 461 00:20:45,390 --> 00:20:47,790 When I call the function, I verify, 462 00:20:47,790 --> 00:20:51,930 first of all, that my function did call getAllProducts. 463 00:20:51,930 --> 00:20:54,780 That function was called and it returned a Promise 464 00:20:54,780 --> 00:20:56,400 that was rejected. 465 00:20:56,400 --> 00:20:58,320 So this should have been the result 466 00:20:58,320 --> 00:21:02,490 that I got back from my ultimate function, zero. 467 00:21:02,490 --> 00:21:05,730 So we can run all those tests, take a deep breath, 468 00:21:05,730 --> 00:21:07,563 hope that they work and they work. 469 00:21:08,790 --> 00:21:09,623 So there we go. 470 00:21:09,623 --> 00:21:12,963 So the key point, two key points to summarize. 471 00:21:14,550 --> 00:21:17,133 When you have functions that return a Promise 472 00:21:17,133 --> 00:21:20,820 that will either resolve or reject, 473 00:21:20,820 --> 00:21:24,120 you have to or you might want to mock that Promise 474 00:21:24,120 --> 00:21:28,290 with either this rejected error or this resolved result. 475 00:21:28,290 --> 00:21:32,970 So in your test, mock the module if you want to. 476 00:21:32,970 --> 00:21:34,620 The function that returns a Promise 477 00:21:34,620 --> 00:21:38,010 either mock that it returns successfully with that result 478 00:21:38,010 --> 00:21:41,343 or mock the fact that it rejects with this error.