1 00:00:06,767 --> 00:00:08,100 - Well, the last two tests we created, 2 00:00:08,100 --> 00:00:10,060 that basic unit test and the table test, 3 00:00:10,060 --> 00:00:11,200 they were fantastic. 4 00:00:11,200 --> 00:00:13,190 Right, we're testing the GET call. 5 00:00:13,190 --> 00:00:15,860 But here's the problem with those two tests. 6 00:00:15,860 --> 00:00:19,130 They require a connection to the outside world. 7 00:00:19,130 --> 00:00:21,220 We're hitting a live sever. 8 00:00:21,220 --> 00:00:24,840 We normally aren't that lucky in our CI environments 9 00:00:24,840 --> 00:00:26,890 when we have access to the outside world. 10 00:00:26,890 --> 00:00:30,870 Now, I always want to be very careful about mocking, 11 00:00:30,870 --> 00:00:32,750 I don't want to mock databases, 12 00:00:32,750 --> 00:00:34,220 I want to use Docker for that. 13 00:00:34,220 --> 00:00:37,490 Certain systems where it's critical that we know 14 00:00:37,490 --> 00:00:40,360 that we're talking to live systems or binary protocols. 15 00:00:40,360 --> 00:00:41,580 Everything is working. 16 00:00:41,580 --> 00:00:43,030 I'd rather use Docker for that, 17 00:00:43,030 --> 00:00:46,090 again, the databases, don't mock databases. 18 00:00:46,090 --> 00:00:47,880 But a lot of things can be mocked, 19 00:00:47,880 --> 00:00:50,770 and these tests that we did run, could be mocked. 20 00:00:50,770 --> 00:00:52,550 Right, like, I don't particularly care, 21 00:00:52,550 --> 00:00:53,970 I know that web servers work. 22 00:00:53,970 --> 00:00:57,950 So I don't care about the http protocols, here. 23 00:00:57,950 --> 00:01:00,500 What I care about is that if I send this request 24 00:01:00,500 --> 00:01:03,580 and I get back the response, that I can process it. 25 00:01:03,580 --> 00:01:05,760 And so what I want to show you is how you can mock 26 00:01:05,760 --> 00:01:09,910 a GET call, already built into Go's standard library 27 00:01:09,910 --> 00:01:10,890 and the language. 28 00:01:10,890 --> 00:01:11,900 And what's nice is, 29 00:01:11,900 --> 00:01:15,470 Go gives us this package called httptest. 30 00:01:15,470 --> 00:01:18,550 We're going to use this to mock these GET calls 31 00:01:18,550 --> 00:01:19,970 and we'll use them again later, 32 00:01:19,970 --> 00:01:23,070 to be able to mock some of our internal stuff. 33 00:01:23,070 --> 00:01:25,370 So, look at what we do here in this code. 34 00:01:25,370 --> 00:01:26,930 Since we're going to be making a GET call 35 00:01:26,930 --> 00:01:30,880 to the goinggo dot web server for that RSS feed, 36 00:01:30,880 --> 00:01:33,350 which is nothing more than an XML document, 37 00:01:33,350 --> 00:01:35,810 what I've done here is I've created a raw string, 38 00:01:35,810 --> 00:01:36,643 right there. 39 00:01:36,643 --> 00:01:37,750 It's called feed, it's raw. 40 00:01:37,750 --> 00:01:39,407 You see the use of those tick marks here 41 00:01:39,407 --> 00:01:41,200 and what those tick marks are doing 42 00:01:41,200 --> 00:01:44,140 is respecting even the carriage return line feeds 43 00:01:44,140 --> 00:01:47,200 and the tabs, or anything I put into that space. 44 00:01:47,200 --> 00:01:50,490 So, this is a RSS document that represents 45 00:01:50,490 --> 00:01:53,120 at least a portion of what we expect to get back, 46 00:01:53,120 --> 00:01:55,850 when I hit the goinggo.net web server. 47 00:01:55,850 --> 00:01:56,683 Great. 48 00:01:56,683 --> 00:01:58,990 Now I've created some structs here, 49 00:01:58,990 --> 00:02:02,310 and with the XML tag, so we can pull this data 50 00:02:02,310 --> 00:02:05,660 when we mock the call and get this raw string back. 51 00:02:05,660 --> 00:02:09,720 We can unmarshel it into our real data structures here. 52 00:02:09,720 --> 00:02:11,700 And do some actual testing. 53 00:02:11,700 --> 00:02:14,920 But the whole key to the mock, is this function right here, 54 00:02:14,920 --> 00:02:15,823 called mockServer. 55 00:02:16,919 --> 00:02:20,260 I want you to notice mockServer is using the pointer 56 00:02:20,260 --> 00:02:24,860 semantics for the server type, inside httptest. 57 00:02:24,860 --> 00:02:28,434 The server type allows us, during unit testing, 58 00:02:28,434 --> 00:02:32,300 to kind of stand up a web service 59 00:02:32,300 --> 00:02:33,860 on some random port 60 00:02:33,860 --> 00:02:35,450 that we'll be able to get back 61 00:02:35,450 --> 00:02:39,810 and write code that we know executes on the call. 62 00:02:39,810 --> 00:02:41,170 Bottom line is this, 63 00:02:41,170 --> 00:02:45,290 when we call NewServer right here on the return, 64 00:02:45,290 --> 00:02:48,700 then NewServer's going to stand up a web service 65 00:02:48,700 --> 00:02:50,750 on a port, that it will tell us. 66 00:02:50,750 --> 00:02:53,420 And when we hit the endpoint that it gives us, 67 00:02:53,420 --> 00:02:56,190 any endpoint that it gives us, it's going execute 68 00:02:56,190 --> 00:02:59,730 this function that I'm defining right here on line 63. 69 00:02:59,730 --> 00:03:02,960 I like when I define literal functions to assign 70 00:03:02,960 --> 00:03:05,580 them to a variable, and then pass them into what I'm doing. 71 00:03:05,580 --> 00:03:07,660 I just find that the code is more readable. 72 00:03:07,660 --> 00:03:11,190 A lot of people like to, kinda, define that function 73 00:03:11,190 --> 00:03:12,023 in the calls. 74 00:03:12,023 --> 00:03:13,670 I'm looking for readability. 75 00:03:13,670 --> 00:03:16,950 So, look at this, a basic handle or function at Go 76 00:03:16,950 --> 00:03:18,300 uses this signature. 77 00:03:18,300 --> 00:03:20,830 The ResponseWriter, which is an interface, 78 00:03:20,830 --> 00:03:23,460 and the request which is a concrete type. 79 00:03:23,460 --> 00:03:27,120 That is a concrete type, this is an interface type. 80 00:03:27,120 --> 00:03:28,420 And what's going to happen is, 81 00:03:28,420 --> 00:03:30,820 is when we hit our mock server, 82 00:03:30,820 --> 00:03:33,430 we're going to write 200 into the response 83 00:03:33,430 --> 00:03:35,130 we're going to set our application to XML. 84 00:03:35,130 --> 00:03:37,410 Just like the goinggo web server would do. 85 00:03:37,410 --> 00:03:41,020 And then, we're going to use this Fprint line function 86 00:03:41,020 --> 00:03:44,650 to take our raw string and to send it, or stream it, 87 00:03:44,650 --> 00:03:45,920 through the ResponseWriter. 88 00:03:45,920 --> 00:03:46,753 Brilliant. 89 00:03:46,753 --> 00:03:49,730 So, no matter what we hit, on this mock server, 90 00:03:49,730 --> 00:03:51,300 this function gets called. 91 00:03:51,300 --> 00:03:55,420 Which means we can mock any http GET call that we want 92 00:03:55,420 --> 00:03:58,370 and from our code perspective, or you know, 93 00:03:58,370 --> 00:04:01,170 it did go out, it didn't really leave the machine 94 00:04:01,170 --> 00:04:04,820 but it did actually go out and do what it had to do. 95 00:04:04,820 --> 00:04:08,683 Okay, so, watch what we do now with our mock server. 96 00:04:09,800 --> 00:04:11,960 We're going to check that our status is okay. 97 00:04:11,960 --> 00:04:13,810 We call the mockServer function 98 00:04:13,810 --> 00:04:16,040 We get back our server pointer. 99 00:04:16,040 --> 00:04:20,660 Now we have stood up a actual web service 100 00:04:20,660 --> 00:04:22,210 and any time we hit it, 101 00:04:22,210 --> 00:04:25,780 it's going to execute this function here. 102 00:04:25,780 --> 00:04:26,990 We have to defer the close 103 00:04:26,990 --> 00:04:28,870 'cause we've always got to be clean. 104 00:04:28,870 --> 00:04:31,250 So, given the need to test downloading content 105 00:04:31,250 --> 00:04:34,830 like we have, when we check this URL, 106 00:04:34,830 --> 00:04:38,350 look at the field, .URL off of our server pointer. 107 00:04:38,350 --> 00:04:39,650 So whatever this endpoint is, 108 00:04:39,650 --> 00:04:40,700 that's what we're going to hit. 109 00:04:40,700 --> 00:04:43,310 We're not going to hit the actual goinggo.net server, 110 00:04:43,310 --> 00:04:45,260 we're going to hit our mock server. 111 00:04:45,260 --> 00:04:48,800 This is going to be local host on some random port. 112 00:04:48,800 --> 00:04:52,710 And if you extend that local host, some random port, 113 00:04:52,710 --> 00:04:55,450 with any sort of URL you want, 114 00:04:55,450 --> 00:04:58,260 that's okay, it's still going to hit this function. 115 00:04:58,260 --> 00:04:59,570 And you can look at the request, 116 00:04:59,570 --> 00:05:02,740 and put some, maybe, conditional logic in here, 117 00:05:02,740 --> 00:05:05,810 for the different actual endpoints 118 00:05:05,810 --> 00:05:08,293 beyond the port that you might want to test. 119 00:05:09,470 --> 00:05:11,210 Great, we expect this status code. 120 00:05:11,210 --> 00:05:13,940 So now we call GET like we always have, 121 00:05:13,940 --> 00:05:16,600 using this local host URL. 122 00:05:16,600 --> 00:05:18,480 And then the rest of the code goes ahead 123 00:05:18,480 --> 00:05:21,920 and checks the status unmarshels into our document. 124 00:05:21,920 --> 00:05:23,700 We just validate some things, 125 00:05:23,700 --> 00:05:25,800 like we've got the right number of items. 126 00:05:25,800 --> 00:05:27,920 So, remember that this test before 127 00:05:27,920 --> 00:05:31,110 took about 800 milliseconds on the network that I'm on. 128 00:05:31,110 --> 00:05:33,480 Let's see how fast it is to run this test 129 00:05:33,480 --> 00:05:37,160 now that we're mocking it and not leaving my machine. 130 00:05:37,160 --> 00:05:39,590 So, I'm already in the folder that we need to be in there. 131 00:05:39,590 --> 00:05:42,160 There's the example3 underscore test. 132 00:05:42,160 --> 00:05:45,510 And I'm going to run test, with the minus v. 133 00:05:45,510 --> 00:05:48,960 What I want you to see is how fast this test ran. 134 00:05:48,960 --> 00:05:53,080 This is 14 milliseconds, not 800 milliseconds, 135 00:05:53,080 --> 00:05:54,620 14 milliseconds. 136 00:05:54,620 --> 00:05:56,580 We didn't leave my machine. 137 00:05:56,580 --> 00:05:59,020 And you can see, this is the endpoint that we hit, 138 00:05:59,020 --> 00:06:01,600 that was given to us by our mock server, 139 00:06:01,600 --> 00:06:04,370 this 49897 is that port. 140 00:06:04,370 --> 00:06:08,220 So, we hit that, when we hit that URL 141 00:06:08,220 --> 00:06:10,860 at that, you know, local host and port, 142 00:06:10,860 --> 00:06:13,920 we ended up executing this code right in here. 143 00:06:13,920 --> 00:06:15,990 And we mocked out the call, 144 00:06:15,990 --> 00:06:17,460 and we got back what we expected, 145 00:06:17,460 --> 00:06:19,690 which was a valid document on the 200. 146 00:06:19,690 --> 00:06:22,920 And look at this, our test that would have ran 147 00:06:22,920 --> 00:06:26,010 for 900 milliseconds that we've had to worry about 148 00:06:26,010 --> 00:06:27,870 having access to from a server, 149 00:06:27,870 --> 00:06:31,070 we now mocked, and I feel very confident that this GET call 150 00:06:31,070 --> 00:06:35,300 works, because our mock is pretty much real as you can get 151 00:06:35,300 --> 00:06:36,330 hitting a server. 152 00:06:36,330 --> 00:06:39,290 And now, it's even better from my perspective is, 153 00:06:39,290 --> 00:06:42,040 it's not just about the happy case. 154 00:06:42,040 --> 00:06:45,470 I can start doing some really nasty things 155 00:06:45,470 --> 00:06:47,950 around what happens if this fails, and that fails, 156 00:06:47,950 --> 00:06:50,220 and things I wouldn't really be able to cause 157 00:06:50,220 --> 00:06:52,130 my external server to do. 158 00:06:52,130 --> 00:06:54,680 I can mock a bunch of failure here, 159 00:06:54,680 --> 00:06:57,000 and validate that we're handling everything 160 00:06:57,000 --> 00:06:58,563 that could possibly happen.