1 00:00:00,000 --> 00:00:02,100 So in this video, I'm going to break down 2 00:00:02,100 --> 00:00:06,860 the structure of unit tests that I think is appropriate 3 00:00:06,860 --> 00:00:09,780 for enterprise and industry level applications. 4 00:00:09,780 --> 00:00:10,980 This is also suitable, of course, 5 00:00:10,980 --> 00:00:12,300 if you're working on your own project 6 00:00:12,300 --> 00:00:15,480 or if you're just two or three team members in your team, 7 00:00:15,480 --> 00:00:18,540 but specifically I'm talking about from my experience 8 00:00:18,540 --> 00:00:21,660 within Microsoft, working on big projects, 9 00:00:21,660 --> 00:00:23,540 I'm talking about hundreds of partners 10 00:00:23,540 --> 00:00:26,380 or hundreds of developers working on the same project. 11 00:00:26,380 --> 00:00:29,300 So the principles that I'm going to outline today 12 00:00:29,300 --> 00:00:32,620 are relevant for projects that have three people, 13 00:00:32,620 --> 00:00:35,100 but they're also relevant for teams 14 00:00:35,100 --> 00:00:37,500 of hundreds of people working on the same project. 15 00:00:37,500 --> 00:00:41,500 So what I want to focus on today is specifically the structure 16 00:00:41,500 --> 00:00:44,660 and how to build your unit test infrastructure 17 00:00:44,660 --> 00:00:49,500 in a way where you're creating a small testing framework 18 00:00:49,500 --> 00:00:53,060 for you and your team in a way that scales well 19 00:00:53,060 --> 00:00:55,540 as you refactor, you add more tests, 20 00:00:55,540 --> 00:00:57,380 more team members are joining, 21 00:00:57,380 --> 00:00:59,820 and the previous ones are leaving, 22 00:00:59,820 --> 00:01:03,580 how to set the correct foundation for your unit tests 23 00:01:03,580 --> 00:01:05,460 to thrive in the long run. 24 00:01:05,460 --> 00:01:07,580 Now, before we begin, I do want to emphasize 25 00:01:07,580 --> 00:01:08,980 that even though I work at Microsoft, 26 00:01:08,980 --> 00:01:10,780 I'm not talking on behalf of Microsoft, 27 00:01:10,780 --> 00:01:13,340 the things that I'm presenting are my personal opinions. 28 00:01:13,340 --> 00:01:15,940 The methodology that I'm going to lay out today 29 00:01:15,940 --> 00:01:17,980 is going to be what I would actually take 30 00:01:17,980 --> 00:01:21,180 if I were to build a project from scratch today 31 00:01:21,180 --> 00:01:22,820 based on my experience. 32 00:01:22,820 --> 00:01:27,820 Now, I've done this specific pattern in multiple projects, 33 00:01:27,820 --> 00:01:30,700 either new projects or projects that I entered 34 00:01:30,700 --> 00:01:32,620 that were already very big, 35 00:01:32,620 --> 00:01:35,980 and it's amazing to see how once you have 36 00:01:35,980 --> 00:01:37,940 the correct structure in place, 37 00:01:37,940 --> 00:01:42,020 then how new tests and new utilities 38 00:01:42,020 --> 00:01:44,620 or test utilities that are added with time 39 00:01:44,620 --> 00:01:48,220 align with the foundation that was laid down. 40 00:01:48,220 --> 00:01:50,980 Okay, so let's jump right in and look at an example. 41 00:01:50,980 --> 00:01:53,100 We're going to use the Booper dinner application. 42 00:01:53,100 --> 00:01:54,660 This is a project that's built 43 00:01:54,660 --> 00:01:56,500 following clean architecture and domain driven design. 44 00:01:56,500 --> 00:01:58,060 Okay, so if we look at what we have over here, 45 00:01:58,060 --> 00:02:01,620 then we're looking under the main folder, 46 00:02:01,620 --> 00:02:03,540 the root folder of our application. 47 00:02:03,540 --> 00:02:06,300 We have right away all our various projects, right? 48 00:02:06,300 --> 00:02:08,380 So this is the actual infrastructure project. 49 00:02:08,380 --> 00:02:09,780 This is the actual contracts project. 50 00:02:09,780 --> 00:02:11,780 So the first thing we want to do is go ahead 51 00:02:11,780 --> 00:02:14,820 and create a source folder where the source code will sit. 52 00:02:14,820 --> 00:02:17,140 So for that, let's say make the source. 53 00:02:17,140 --> 00:02:19,020 So we have the source folder, 54 00:02:19,020 --> 00:02:20,420 which contains the source code. 55 00:02:20,420 --> 00:02:23,180 We have the documentation and the requests 56 00:02:23,180 --> 00:02:24,420 in corresponding folders. 57 00:02:24,420 --> 00:02:25,820 And then we have here general things 58 00:02:25,820 --> 00:02:29,700 like the global JSON, the directory.build.props 59 00:02:29,700 --> 00:02:32,260 and the solution file. 60 00:02:32,260 --> 00:02:34,140 So we have here everything that we want. 61 00:02:34,140 --> 00:02:36,540 The next thing we want to do is create a new folder 62 00:02:36,540 --> 00:02:37,380 for the tests. 63 00:02:37,380 --> 00:02:39,380 So I say make the error tests. 64 00:02:39,380 --> 00:02:42,460 Okay, like we said, we have the source and the tests. 65 00:02:42,460 --> 00:02:44,380 All our tests will sit under the tests. 66 00:02:44,380 --> 00:02:47,660 Now we're going to create a folder for each type of tests. 67 00:02:47,660 --> 00:02:49,780 So let's create a folder called unit test 68 00:02:49,780 --> 00:02:52,620 and any other test type that you would have 69 00:02:52,620 --> 00:02:54,340 would also sit in the corresponding folder. 70 00:02:54,340 --> 00:02:56,460 I'll create a few just for reference, so you have it. 71 00:02:56,460 --> 00:02:57,900 Okay, now the reason why we want to do this 72 00:02:57,900 --> 00:03:01,180 is as you can see, we already have five projects over here 73 00:03:01,180 --> 00:03:03,980 where each one of them will probably have unit tests 74 00:03:03,980 --> 00:03:06,220 or almost each one of them is going to have unit tests. 75 00:03:06,220 --> 00:03:08,140 But if it also has integration tests, 76 00:03:08,140 --> 00:03:10,420 then this starts to become pretty crowded 77 00:03:10,420 --> 00:03:14,300 if everything sits just over here under the test folder. 78 00:03:14,300 --> 00:03:15,180 Okay, so now that we have this, 79 00:03:15,180 --> 00:03:18,260 let's go ahead and create the actual test project. 80 00:03:18,260 --> 00:03:20,380 So for that, let's use the net CLI. 81 00:03:20,380 --> 00:03:24,500 So over here, let's go to our tests project 82 00:03:24,500 --> 00:03:25,820 specifically into the unit test 83 00:03:25,820 --> 00:03:30,180 and let's create here a new X unit test project. 84 00:03:30,180 --> 00:03:33,100 Okay, so the name of the project is simply the name 85 00:03:33,100 --> 00:03:34,780 of the project that we're testing 86 00:03:34,780 --> 00:03:37,420 with the unit test suffix. 87 00:03:37,420 --> 00:03:41,180 Okay, so I went ahead and created a test project per project 88 00:03:41,180 --> 00:03:43,340 other than the contracts project. 89 00:03:43,340 --> 00:03:46,060 So the contract project is simply a class library 90 00:03:46,060 --> 00:03:48,340 that contains the definition of our API. 91 00:03:48,340 --> 00:03:51,460 And it doesn't need unit tests at least as it stands today. 92 00:03:51,460 --> 00:03:54,060 The next thing we want to do is we want to go 93 00:03:54,060 --> 00:03:56,500 to the solution file and update it 94 00:03:56,500 --> 00:03:58,140 to reference all the new projects. 95 00:03:58,140 --> 00:04:00,500 So what I'm going to do for that is I'm simply going 96 00:04:00,500 --> 00:04:04,780 to delete the SLN file, create a new one, 97 00:04:04,780 --> 00:04:06,580 let's say dot a new SLN. 98 00:04:06,580 --> 00:04:09,700 And we're going to simply add all the projects that exist now 99 00:04:09,700 --> 00:04:13,100 because we also changed the structure of the files. 100 00:04:13,100 --> 00:04:17,300 So the previous reference to the projects as it was before 101 00:04:17,300 --> 00:04:18,300 isn't valid anymore. 102 00:04:18,300 --> 00:04:21,620 So dot net SLN add and we want to add a reference 103 00:04:21,620 --> 00:04:24,420 to all the CS projects that exist recursively. 104 00:04:24,420 --> 00:04:28,060 So running this will create the solution file as we want. 105 00:04:28,060 --> 00:04:30,700 The next thing we're going to do is we're going to look 106 00:04:30,700 --> 00:04:33,740 at the command handler that we're going to write the test for. 107 00:04:33,740 --> 00:04:38,380 Now the emphasis of this video is not the actual test 108 00:04:38,380 --> 00:04:39,620 that we're going to write, 109 00:04:39,620 --> 00:04:43,060 but it's all the infrastructure around it building a small 110 00:04:43,060 --> 00:04:46,180 framework that's specific for your application 111 00:04:46,180 --> 00:04:47,300 when you're building tests. 112 00:04:47,300 --> 00:04:50,520 So I want you, even though we're looking at the code 113 00:04:50,520 --> 00:04:51,820 that we're using in this video, 114 00:04:51,820 --> 00:04:54,380 I do want you to imagine the code that you're working on 115 00:04:54,380 --> 00:04:57,140 in your code base and think how you can apply some 116 00:04:57,140 --> 00:05:00,700 of the principles to create structure in your test project. 117 00:05:00,700 --> 00:05:04,460 So we're going to write the test for the menu command handler. 118 00:05:04,460 --> 00:05:07,060 So this one over here. 119 00:05:07,060 --> 00:05:10,580 And what we have is a simple command handler 120 00:05:10,580 --> 00:05:14,580 that all we're doing as part of the logic of this method 121 00:05:14,580 --> 00:05:18,980 is we're creating a menu aggregate based 122 00:05:18,980 --> 00:05:21,020 on the create menu command. 123 00:05:21,020 --> 00:05:24,380 We're adding this menu to the menu repository 124 00:05:24,380 --> 00:05:26,860 and we're returning the menu over here. 125 00:05:26,860 --> 00:05:28,340 So it's very straightforward. 126 00:05:28,340 --> 00:05:30,220 There isn't a lot of logic over here. 127 00:05:30,220 --> 00:05:32,540 Again, we're going to write the code for this, 128 00:05:32,540 --> 00:05:35,340 but I want you to notice the structure 129 00:05:35,340 --> 00:05:38,420 and the framework that we're building as we're going along. 130 00:05:38,420 --> 00:05:40,940 The first thing we want to do is we want each one 131 00:05:40,940 --> 00:05:45,420 of our tests to sit in the corresponding folder path 132 00:05:45,420 --> 00:05:48,060 of the original source code. 133 00:05:48,060 --> 00:05:51,380 So we can see over here the folder structure leading 134 00:05:51,380 --> 00:05:54,220 to our handler because the namespace corresponds 135 00:05:54,220 --> 00:05:55,420 to the folder structure. 136 00:05:55,420 --> 00:05:57,220 So we can see we have the menus folder, 137 00:05:57,220 --> 00:06:00,380 then the commands folder, then the create menu folder. 138 00:06:00,380 --> 00:06:03,500 So let's go ahead and recreate the same hierarchy 139 00:06:03,500 --> 00:06:04,940 in the test project. 140 00:06:04,940 --> 00:06:07,900 So over here we can go ahead and say menus, 141 00:06:07,900 --> 00:06:10,380 commands, create menu. 142 00:06:10,380 --> 00:06:12,340 This will create the three folders 143 00:06:12,340 --> 00:06:13,980 and the name of the class we want over here 144 00:06:13,980 --> 00:06:18,860 is the name of the source file with tests suffix. 145 00:06:18,860 --> 00:06:23,460 So let's say create menu command handler tests. 146 00:06:23,460 --> 00:06:25,100 Okay, so we have our test class. 147 00:06:25,100 --> 00:06:27,860 The next thing I want you to notice is the following. 148 00:06:27,860 --> 00:06:32,220 So we have a single test file corresponding 149 00:06:32,220 --> 00:06:34,300 to the source code file. 150 00:06:34,300 --> 00:06:38,180 Sometimes the source file, just for legacy reasons, 151 00:06:38,180 --> 00:06:39,660 may be really big. 152 00:06:39,660 --> 00:06:42,860 This means that if the source code is very long, 153 00:06:42,860 --> 00:06:45,820 then the test file will be much, much longer. 154 00:06:45,820 --> 00:06:48,340 And of course that isn't scalable, maintainable, 155 00:06:48,340 --> 00:06:49,540 or fun to work with. 156 00:06:49,540 --> 00:06:54,540 If you have many sub scenarios inside the same source code file, 157 00:06:54,540 --> 00:06:58,500 then you may want to do something like the following 158 00:06:58,500 --> 00:07:02,940 and simply create multiple files per sub scenario. 159 00:07:02,940 --> 00:07:04,580 So let's say you have a sub scenario 160 00:07:04,580 --> 00:07:06,700 of creating a menu inside this. 161 00:07:06,700 --> 00:07:09,380 So you would say create menu tests, right? 162 00:07:09,380 --> 00:07:11,060 Something like the following. 163 00:07:11,060 --> 00:07:13,460 And you would have a file that would contain 164 00:07:13,460 --> 00:07:17,380 the logical subgroup of tests for that scenario. 165 00:07:17,380 --> 00:07:20,060 So if you're writing the first test for this God file, 166 00:07:20,060 --> 00:07:22,900 you want to think about what will happen 167 00:07:22,900 --> 00:07:27,940 in the next 10 pull requests when all the following tests 168 00:07:27,940 --> 00:07:30,220 will be added and what will happen to the file 169 00:07:30,220 --> 00:07:34,460 will it become a God file and should you already put 170 00:07:34,460 --> 00:07:37,580 the initial infrastructure of creating files 171 00:07:37,580 --> 00:07:39,860 specifically for a smaller scope. 172 00:07:39,860 --> 00:07:40,900 Okay, the next thing I want to do 173 00:07:40,900 --> 00:07:43,540 is talk about the test naming. 174 00:07:43,540 --> 00:07:45,100 So for us to be able to see something, 175 00:07:45,100 --> 00:07:47,700 I closed the folder view, I'll split the screen, 176 00:07:47,700 --> 00:07:49,100 and on the right hand side, 177 00:07:49,100 --> 00:07:52,220 I'll put the source code that we're testing. 178 00:07:52,220 --> 00:07:55,180 For the test name, I go with the following structure. 179 00:07:55,180 --> 00:07:58,700 So let's say public void and it's going to be divided 180 00:07:58,700 --> 00:07:59,780 into three parts. 181 00:07:59,780 --> 00:08:04,780 So T1, T2 and T3, where T1 is what we're testing. 182 00:08:04,780 --> 00:08:09,620 So the system under test, T2 is the specific scenario 183 00:08:09,620 --> 00:08:12,100 that we're testing, so scenario. 184 00:08:12,100 --> 00:08:15,780 And T3 is the expected outcome, right? 185 00:08:15,780 --> 00:08:17,940 What we expect to happen in this scenario? 186 00:08:17,940 --> 00:08:19,180 So expected outcome. 187 00:08:19,180 --> 00:08:20,300 For the system under test, 188 00:08:20,300 --> 00:08:22,460 the reason why I think this is important 189 00:08:22,460 --> 00:08:25,540 is we want from the test name to know 190 00:08:25,540 --> 00:08:28,300 what part of the code we're talking about. 191 00:08:28,300 --> 00:08:31,500 So when I see this failing in my CI/CD, 192 00:08:31,500 --> 00:08:34,580 I see, okay, what's failing is for in our case, 193 00:08:34,580 --> 00:08:36,860 handling the create menu command. 194 00:08:36,860 --> 00:08:38,780 So I already know to associate it 195 00:08:38,780 --> 00:08:41,780 with the corresponding part in our application 196 00:08:41,780 --> 00:08:42,620 that is failing. 197 00:08:42,620 --> 00:08:45,900 So this is basically what we're testing, 198 00:08:45,900 --> 00:08:50,380 and it doesn't have to be the exact name of the method 199 00:08:50,380 --> 00:08:53,180 or the class that we're testing. 200 00:08:53,180 --> 00:08:54,580 So in our case, it doesn't need to be 201 00:08:54,580 --> 00:08:56,260 create menu command handler, 202 00:08:56,260 --> 00:08:59,340 but it needs to be the logical association 203 00:08:59,340 --> 00:09:01,860 to the piece of code that we want to test, okay? 204 00:09:01,860 --> 00:09:03,420 So this is what we're testing. 205 00:09:03,420 --> 00:09:04,780 The next one is the scenario. 206 00:09:04,780 --> 00:09:08,460 So each one of our tests is testing a specific scenario. 207 00:09:08,460 --> 00:09:11,420 So perhaps let's say here, this is what we're testing. 208 00:09:11,420 --> 00:09:15,300 This is the logical component that we're testing, 209 00:09:15,300 --> 00:09:17,460 and the expected outcome like it sounds. 210 00:09:17,460 --> 00:09:22,460 So what we expect the logical components to do. 211 00:09:22,460 --> 00:09:25,060 Like I said, unit testing is a highly opinionated 212 00:09:25,060 --> 00:09:28,780 and specifically test names is highly opinionated. 213 00:09:28,780 --> 00:09:33,300 So this is specifically what I think is the best approach 214 00:09:33,300 --> 00:09:37,380 after seeing many projects using various strategies. 215 00:09:37,380 --> 00:09:39,820 The reason why I like this approach, 216 00:09:39,820 --> 00:09:42,140 even though we're putting over here 217 00:09:42,140 --> 00:09:44,980 perhaps details of the name of the class. 218 00:09:44,980 --> 00:09:47,940 So we might, when changing the name of the class 219 00:09:47,940 --> 00:09:50,780 or refactoring, we might need to change the name 220 00:09:50,780 --> 00:09:53,180 of T1 in 30 tests. 221 00:09:53,180 --> 00:09:54,900 So yes, that's true. 222 00:09:54,900 --> 00:09:56,500 But the reason I like that, again, 223 00:09:56,500 --> 00:09:58,380 is when I see a test failing. 224 00:09:58,380 --> 00:10:01,460 So as application grows, we have thousands of tests, 225 00:10:01,460 --> 00:10:04,300 a random test somewhere in the code base breaks. 226 00:10:04,300 --> 00:10:06,300 I know how to do the logical association 227 00:10:06,300 --> 00:10:08,780 with the specific code that failed. 228 00:10:08,780 --> 00:10:11,140 And for T2 and T3, what I like about this 229 00:10:11,140 --> 00:10:13,700 is that it tells you what the test is going to do, 230 00:10:13,700 --> 00:10:16,620 what you're expecting to have in the outcome. 231 00:10:16,620 --> 00:10:18,260 And once you have this structure 232 00:10:18,260 --> 00:10:20,060 for all the tests in your code base, 233 00:10:20,060 --> 00:10:21,860 so it's very easy to open a random test 234 00:10:21,860 --> 00:10:24,900 and understand what it does without having to read 235 00:10:24,900 --> 00:10:27,540 through the implementation of the method. 236 00:10:27,540 --> 00:10:31,980 So in our case, let's say handle, create menu command, 237 00:10:31,980 --> 00:10:35,060 and the scenario that we want to test in our case 238 00:10:35,060 --> 00:10:39,500 is, for example, when menu is valid, 239 00:10:39,500 --> 00:10:43,780 then what we want to happen is that it should be added 240 00:10:43,780 --> 00:10:44,740 and returned. 241 00:10:44,740 --> 00:10:48,620 So let's say should create and return menu. 242 00:10:48,620 --> 00:10:50,300 Unless I want to contrast what we're doing 243 00:10:50,300 --> 00:10:52,300 with some other very common approaches. 244 00:10:52,300 --> 00:10:54,020 So this is something that I've seen 245 00:10:54,020 --> 00:10:58,060 in way too many code bases where the main flow, 246 00:10:58,060 --> 00:11:01,660 the flow that the unit that we're talking about 247 00:11:01,660 --> 00:11:05,980 was created for would be called test_happyflow. 248 00:11:05,980 --> 00:11:07,660 What does happyflow even mean? 249 00:11:07,660 --> 00:11:10,300 Should we be sending a metric when we're creating 250 00:11:10,300 --> 00:11:11,140 a new menu? 251 00:11:11,140 --> 00:11:13,180 Should we be logging the information? 252 00:11:13,180 --> 00:11:14,620 Should we be raising an event? 253 00:11:14,620 --> 00:11:16,340 Should we be adding it to the database? 254 00:11:16,340 --> 00:11:18,220 Should we not be returning the menu? 255 00:11:18,220 --> 00:11:20,660 This doesn't have any details about 256 00:11:20,660 --> 00:11:23,220 what's actually supposed to happen. 257 00:11:23,220 --> 00:11:26,740 And it would require me, as someone joining the codebase, 258 00:11:26,740 --> 00:11:30,100 to go through the test method and understand 259 00:11:30,100 --> 00:11:33,100 what the happyflow is. 260 00:11:33,100 --> 00:11:38,020 And when this test doesn't only contain one specific scenario, 261 00:11:38,020 --> 00:11:41,140 many times this test becomes a big test that tests 262 00:11:41,140 --> 00:11:43,060 multiple scenarios in the same method. 263 00:11:43,060 --> 00:11:45,540 It becomes a mess, not only to understand, 264 00:11:45,540 --> 00:11:47,260 but also to refactor. 265 00:11:47,260 --> 00:11:48,980 And every time you add something, 266 00:11:48,980 --> 00:11:51,420 you got to think, is this part of the happyflow? 267 00:11:51,420 --> 00:11:54,820 If yes, I need to go to that method, update it, and so on. 268 00:11:54,820 --> 00:11:56,700 So I highly dislike this approach. 269 00:11:56,700 --> 00:11:59,620 This is probably the worst approach, in my opinion, 270 00:11:59,620 --> 00:12:02,300 when it comes to naming the test. 271 00:12:02,300 --> 00:12:04,140 The next one is something like the following. 272 00:12:04,140 --> 00:12:06,780 This is very common, and it's just suggested 273 00:12:06,780 --> 00:12:07,940 by many of the pros. 274 00:12:07,940 --> 00:12:10,540 The reason I dislike this is because it's lacking 275 00:12:10,540 --> 00:12:13,460 the structure needed in a team environment 276 00:12:13,460 --> 00:12:16,860 to create tests that look in a uniform way. 277 00:12:16,860 --> 00:12:20,660 What I mean by that is that this is a great name 278 00:12:20,660 --> 00:12:22,460 that perhaps we thought of, 279 00:12:22,460 --> 00:12:26,140 but someone else may call it something like the following. 280 00:12:26,140 --> 00:12:28,780 Each one of these two names is a valid name 281 00:12:28,780 --> 00:12:31,740 for the test that we want to write, 282 00:12:31,740 --> 00:12:33,500 but because it lacks structure, 283 00:12:33,500 --> 00:12:36,540 it requires more cognitive load to understand 284 00:12:36,540 --> 00:12:39,820 what we're testing, what the system under test is, 285 00:12:39,820 --> 00:12:42,900 and what the expected behavior is. 286 00:12:42,900 --> 00:12:45,580 In my opinion, when you have something like this, 287 00:12:45,580 --> 00:12:48,140 then even if team members slowly create 288 00:12:48,140 --> 00:12:51,500 their own style of naming that is a bit different, 289 00:12:51,500 --> 00:12:55,060 it still stays more or less under the same umbrella 290 00:12:55,060 --> 00:12:56,180 of test naming. 291 00:12:56,180 --> 00:12:59,220 And approach number three, which is also pretty common, 292 00:12:59,220 --> 00:13:02,820 is something like this, but very fluid rules. 293 00:13:02,820 --> 00:13:04,820 So if you need to add another underscore somewhere 294 00:13:04,820 --> 00:13:06,900 in the middle, then go ahead and do that. 295 00:13:06,900 --> 00:13:10,260 And very quickly, you'll have tests 296 00:13:10,260 --> 00:13:11,540 that are written something like this, 297 00:13:11,540 --> 00:13:13,220 specifically within Microsoft, 298 00:13:13,220 --> 00:13:15,540 something like the following is super common. 299 00:13:15,540 --> 00:13:17,220 So you'll have test underscore, 300 00:13:17,220 --> 00:13:19,660 and then, for example, the system under test, 301 00:13:19,660 --> 00:13:23,580 and something else, maybe some other sub scenarios 302 00:13:23,580 --> 00:13:25,780 that we're testing, this not only becomes long, 303 00:13:25,780 --> 00:13:27,260 but requires also the cognitive load 304 00:13:27,260 --> 00:13:29,700 of understanding what this method is testing, 305 00:13:29,700 --> 00:13:33,140 and also when you're writing a test in this codebase, 306 00:13:33,140 --> 00:13:36,260 then it requires more time to think 307 00:13:36,260 --> 00:13:38,500 what the name should be to align 308 00:13:38,500 --> 00:13:40,660 with the other tests in this class. 309 00:13:40,660 --> 00:13:43,100 So this is what I'm suggesting you can do 310 00:13:43,100 --> 00:13:45,140 of course, whatever you want, 311 00:13:45,140 --> 00:13:47,860 but in my opinion, this is the best approach. 312 00:13:47,860 --> 00:13:48,940 Okay, now you may be asking yourself, 313 00:13:48,940 --> 00:13:52,020 why are we talking so much about the name of the test? 314 00:13:52,020 --> 00:13:54,820 If we're only running code, the test's other code, 315 00:13:54,820 --> 00:13:59,060 then why do we even care what the name of the method 316 00:13:59,060 --> 00:14:01,820 that isn't even going to run as part of production code, 317 00:14:01,820 --> 00:14:03,460 who even cares what the name is? 318 00:14:03,460 --> 00:14:05,940 In my opinion, having a strong convention 319 00:14:05,940 --> 00:14:09,860 for the name of the test is actually very important. 320 00:14:09,860 --> 00:14:13,020 The reason for that is as the application grows, 321 00:14:13,020 --> 00:14:15,620 we have hundreds of tests, thousands of tests, 322 00:14:15,620 --> 00:14:20,060 and if each one of the tests is written in a different way, 323 00:14:20,060 --> 00:14:22,900 it becomes much harder to write the tests, 324 00:14:22,900 --> 00:14:24,940 trying to align with the code around you. 325 00:14:24,940 --> 00:14:27,260 Also, if some random test is failing 326 00:14:27,260 --> 00:14:29,420 and you want to understand why it's failing, 327 00:14:29,420 --> 00:14:32,900 it will save you a lot of time in trying to understand 328 00:14:32,900 --> 00:14:33,740 what happened. 329 00:14:33,740 --> 00:14:37,020 Bigger projects with more team members usually means 330 00:14:37,020 --> 00:14:39,140 that there's going to be less focus 331 00:14:39,140 --> 00:14:41,740 on the test files during code review. 332 00:14:41,740 --> 00:14:45,820 This means that the threshold for writing bad code 333 00:14:45,820 --> 00:14:50,180 for tests is much lower than the actual production code. 334 00:14:50,180 --> 00:14:53,140 If there aren't good conventions out of the box 335 00:14:53,140 --> 00:14:55,100 as the project is set up, 336 00:14:55,100 --> 00:14:57,660 then people will copy paste bad code 337 00:14:57,660 --> 00:15:01,740 and it'll require much more development time 338 00:15:01,740 --> 00:15:05,180 as time goes on because it's not well structured. 339 00:15:05,180 --> 00:15:07,980 Even if this conversation seems a bit ridiculous to you, 340 00:15:07,980 --> 00:15:11,100 I do want you to remember that some projects 341 00:15:11,100 --> 00:15:14,060 can really benefit from having this type of convention. 342 00:15:14,060 --> 00:15:15,740 So with that out of the way, 343 00:15:15,740 --> 00:15:17,700 that's the name of the test that we're going with. 344 00:15:17,700 --> 00:15:18,740 The next thing we want to do 345 00:15:18,740 --> 00:15:20,260 is we want to write the actual code. 346 00:15:20,260 --> 00:15:23,060 So I'm a big proponent of a range, act assert. 347 00:15:23,060 --> 00:15:25,580 So let's say over here, arrange, act assert, 348 00:15:25,580 --> 00:15:26,980 and I'm not going to go into detail 349 00:15:26,980 --> 00:15:30,700 because I'm assuming you know the theory of unit tests. 350 00:15:30,700 --> 00:15:32,580 So in the arrange what we want to do 351 00:15:32,580 --> 00:15:36,500 is we want to somehow get hold of a valid menu. 352 00:15:36,500 --> 00:15:39,660 In the act, we want to invoke the handler 353 00:15:39,660 --> 00:15:41,620 and in the assert we want to check two things. 354 00:15:41,620 --> 00:15:44,020 The first one is that the correct menu 355 00:15:44,020 --> 00:15:46,940 was created based on the command that we gave 356 00:15:46,940 --> 00:15:49,540 and the second one is that it was actually added 357 00:15:49,540 --> 00:15:51,620 to the underlying repository. 358 00:15:51,620 --> 00:15:56,620 So let's say that it correct menu created based on command 359 00:15:56,620 --> 00:16:02,780 and number two menu added to repository. 360 00:16:02,780 --> 00:16:06,060 So the first thing we want to do is we want to get hold 361 00:16:06,060 --> 00:16:10,020 of a valid create menu command 362 00:16:10,020 --> 00:16:13,060 and for that we're going to start creating 363 00:16:13,060 --> 00:16:16,980 some mini framework for our specific project. 364 00:16:16,980 --> 00:16:20,140 So let's open the folder structure and look where we are. 365 00:16:20,140 --> 00:16:21,100 Okay, so again, we're over here. 366 00:16:21,100 --> 00:16:23,460 We have the menus folder inside that the commands 367 00:16:23,460 --> 00:16:26,700 and the create menu and over here is our test class. 368 00:16:26,700 --> 00:16:29,580 Now we want to create a utility specifically 369 00:16:29,580 --> 00:16:33,740 for creating the create menu command object. 370 00:16:33,740 --> 00:16:35,740 Now the question is where do you think 371 00:16:35,740 --> 00:16:38,020 we should place this utility? 372 00:16:38,020 --> 00:16:40,220 What most projects do is the following. 373 00:16:40,220 --> 00:16:44,020 So they would have over here in the top folder 374 00:16:44,020 --> 00:16:47,060 of the project, they would have something like test utils 375 00:16:47,060 --> 00:16:50,500 and the various logic will sit under here. 376 00:16:50,500 --> 00:16:53,260 The reason why we want to avoid this is because 377 00:16:53,260 --> 00:16:57,260 as the application grows, this becomes a God folder 378 00:16:57,260 --> 00:16:59,820 for all the various utilities even without talking 379 00:16:59,820 --> 00:17:02,380 about how it's structured deeper inside. 380 00:17:02,380 --> 00:17:05,500 What I like doing is putting the utility class 381 00:17:05,500 --> 00:17:08,980 as close to the components that are using it as possible. 382 00:17:08,980 --> 00:17:13,180 That means it will sit nested inside the folders 383 00:17:13,180 --> 00:17:15,940 as deep as possible that still allows 384 00:17:15,940 --> 00:17:18,020 the various components that are using it to use it. 385 00:17:18,020 --> 00:17:19,980 Because in our case, we're talking about a utility 386 00:17:19,980 --> 00:17:22,740 for creating the create menu command object. 387 00:17:22,740 --> 00:17:24,860 This probably won't be needed outside 388 00:17:24,860 --> 00:17:26,420 of this commands folder. 389 00:17:26,420 --> 00:17:29,220 So for that reason, we're going to create over here 390 00:17:29,220 --> 00:17:33,140 that test utils class and the utilities that are needed 391 00:17:33,140 --> 00:17:36,780 for this sub component and inside recursively 392 00:17:36,780 --> 00:17:38,060 will sit over here. 393 00:17:38,060 --> 00:17:40,780 Now, of course, as application grows, things change. 394 00:17:40,780 --> 00:17:43,580 So you can take the utility that's sitting 395 00:17:43,580 --> 00:17:46,980 in a nested folder and put it outside. 396 00:17:46,980 --> 00:17:48,340 So in our case, this is what we want. 397 00:17:48,340 --> 00:17:53,340 So let's go ahead and create the create menu command utils file. 398 00:17:53,340 --> 00:17:56,180 Okay, so it's tomorrow because I'm a parent 399 00:17:56,180 --> 00:17:58,380 and I had to stop filming yesterday, 400 00:17:58,380 --> 00:17:59,940 continuing where we left off. 401 00:17:59,940 --> 00:18:02,900 So like we said, we want to create the create menu command 402 00:18:02,900 --> 00:18:05,140 and each one of the commands looks as following. 403 00:18:05,140 --> 00:18:08,140 What I'll do is I'll split the screen and on the right, 404 00:18:08,140 --> 00:18:11,060 I'll put the command that we're trying to create. 405 00:18:11,060 --> 00:18:16,060 So like we said, each one of the create menu commands 406 00:18:16,060 --> 00:18:18,740 has a name and a description and the host ID, 407 00:18:18,740 --> 00:18:22,300 which is the ID of the host that's trying to create the menu. 408 00:18:22,300 --> 00:18:24,820 Then we have a list of sections in each one of the sections, 409 00:18:24,820 --> 00:18:28,340 has a name and a description and also a list of items 410 00:18:28,340 --> 00:18:31,460 where each one of the items also has a name and a description. 411 00:18:31,460 --> 00:18:34,060 Now, if you're imagining a menu in a restaurant, 412 00:18:34,060 --> 00:18:36,700 then as you know, each menu has a lot of sections 413 00:18:36,700 --> 00:18:38,220 and each section has a lot of items. 414 00:18:38,220 --> 00:18:41,420 I'll put the JSON representation of the menu on the screen 415 00:18:41,420 --> 00:18:42,500 so you can pause the video. 416 00:18:42,500 --> 00:18:45,820 And once you have that imagined, then we can continue. 417 00:18:45,820 --> 00:18:49,300 So another question is how do we create one of these command 418 00:18:49,300 --> 00:18:53,820 objects in a way that's also small building blocks 419 00:18:53,820 --> 00:18:55,980 where many unit tests can use it? 420 00:18:55,980 --> 00:19:00,220 And also it's not too generic requiring each one of the tests 421 00:19:00,220 --> 00:19:03,900 using this utils class to write a lot of duplicate code. 422 00:19:03,900 --> 00:19:05,540 But before we do that, we need to add a reference 423 00:19:05,540 --> 00:19:08,300 from the test project to the source code project. 424 00:19:08,300 --> 00:19:10,180 So for that, let's say, don't let add 425 00:19:10,180 --> 00:19:14,940 and we want to add a reference from the unit tests project 426 00:19:14,940 --> 00:19:18,700 to the original source code that's sitting behind it. 427 00:19:18,700 --> 00:19:21,140 Then we can say the following, so public static, 428 00:19:21,140 --> 00:19:25,420 what we want to create is one of these guys over here. 429 00:19:25,420 --> 00:19:26,700 So that's what we want to create. 430 00:19:26,700 --> 00:19:29,620 Let's call it create command. 431 00:19:29,620 --> 00:19:32,900 So let's say we're here, this returns a new create 432 00:19:32,900 --> 00:19:37,260 menu command and let's populate it with some values. 433 00:19:37,260 --> 00:19:41,900 Now, because we want to have various test constants 434 00:19:41,900 --> 00:19:44,700 that we're going to use for the various objects. 435 00:19:44,700 --> 00:19:48,620 So for example, the menu name, instead of rewriting it 436 00:19:48,620 --> 00:19:51,380 in hard-coded strings across our test project, 437 00:19:51,380 --> 00:19:53,580 we want to have it defined in one place. 438 00:19:53,580 --> 00:19:57,340 Because these are utilities that are across our test project, 439 00:19:57,340 --> 00:20:01,460 then we don't want it inside the test details over here. 440 00:20:01,460 --> 00:20:03,180 So again, I'm reminding you that we created 441 00:20:03,180 --> 00:20:06,420 the test details inside the command folder, 442 00:20:06,420 --> 00:20:08,900 but we'll want that inside the test details 443 00:20:08,900 --> 00:20:10,820 of the entire test project. 444 00:20:10,820 --> 00:20:13,700 Over here, let's create a folder called constants 445 00:20:13,700 --> 00:20:16,260 and this will contain all the constants 446 00:20:16,260 --> 00:20:18,180 for our test project. 447 00:20:18,180 --> 00:20:22,900 Now, instead of creating a single test constants file, 448 00:20:22,900 --> 00:20:25,900 which will become a God file as time goes on, 449 00:20:25,900 --> 00:20:27,700 instead what we're going to do is we're going to take 450 00:20:27,700 --> 00:20:32,340 the following approach, we're going to say constants.menu.cs 451 00:20:32,340 --> 00:20:34,820 and this will contain all the constants 452 00:20:34,820 --> 00:20:38,580 specifically for the menu feature. 453 00:20:38,580 --> 00:20:43,580 So public static partial class constants 454 00:20:43,580 --> 00:20:48,860 and what this will contain is another static class 455 00:20:48,860 --> 00:20:50,980 called menu and over here, 456 00:20:50,980 --> 00:20:54,340 we're going to have public const string name. 457 00:20:54,340 --> 00:20:55,460 This will be the name of the menu 458 00:20:55,460 --> 00:20:58,140 that we'll use across our test project 459 00:20:58,140 --> 00:21:01,860 and let's call this menu name and for the description. 460 00:21:01,860 --> 00:21:03,580 So let's do the same thing, 461 00:21:03,580 --> 00:21:06,580 simply replace where it says name with description 462 00:21:06,580 --> 00:21:09,580 and now we have the menu description. 463 00:21:09,580 --> 00:21:13,140 Okay, so I did the same thing for the section and the item. 464 00:21:13,140 --> 00:21:15,980 So we have menu section name, menu section description 465 00:21:15,980 --> 00:21:19,140 and same thing for the item, but with item. 466 00:21:19,140 --> 00:21:20,300 Now that we have this out of the way, 467 00:21:20,300 --> 00:21:21,900 the last thing that we're missing 468 00:21:21,900 --> 00:21:24,820 is the host ID over here. 469 00:21:24,820 --> 00:21:27,860 Now, because the host ID belongs to the host, 470 00:21:27,860 --> 00:21:29,580 then similar to what we have over here, 471 00:21:29,580 --> 00:21:30,980 that's great, another file 472 00:21:30,980 --> 00:21:33,860 and let's call it constants.host.cs 473 00:21:33,860 --> 00:21:36,100 and this is going to be similar to what we have over here. 474 00:21:36,100 --> 00:21:39,140 So let's simply copy, paste what we have, 475 00:21:39,140 --> 00:21:42,340 change this from menu to host, 476 00:21:42,340 --> 00:21:45,620 let's replace everything we have over here 477 00:21:45,620 --> 00:21:48,860 and let's add the host ID. 478 00:21:48,860 --> 00:21:53,180 So let's say public static read-only host ID, 479 00:21:53,180 --> 00:21:56,220 this is coming from the domain project. 480 00:21:56,220 --> 00:21:59,260 So you'll have to add, I did this off camera, 481 00:21:59,260 --> 00:22:00,980 you'll have to add the reference 482 00:22:00,980 --> 00:22:03,020 from that application unit tests 483 00:22:03,020 --> 00:22:05,780 to the domain project similar to what we did before. 484 00:22:05,780 --> 00:22:07,940 So let's say host ID, let's add the reference 485 00:22:07,940 --> 00:22:10,060 and let's call it ID and I'm reminding you 486 00:22:10,060 --> 00:22:14,460 that the host ID looks as follows. 487 00:22:14,460 --> 00:22:16,820 So we have over here the create method 488 00:22:16,820 --> 00:22:17,940 that received the string 489 00:22:17,940 --> 00:22:20,780 and returns a new host ID object. 490 00:22:20,780 --> 00:22:22,300 So what we're going to do is we're going to say 491 00:22:22,300 --> 00:22:25,100 host ID equals host ID dot create 492 00:22:25,100 --> 00:22:28,100 and over here we'll give it something, let's say host ID. 493 00:22:28,100 --> 00:22:29,420 The reason why I like this approach 494 00:22:29,420 --> 00:22:33,940 is because now each one of our features or resources 495 00:22:33,940 --> 00:22:38,940 has its own smaller scope where it contains only the constants 496 00:22:38,940 --> 00:22:41,580 for that specific type. 497 00:22:41,580 --> 00:22:44,420 Then as application grows, you add more files, 498 00:22:44,420 --> 00:22:47,140 each one with its specific scope 499 00:22:47,140 --> 00:22:48,980 and it doesn't become a God file. 500 00:22:48,980 --> 00:22:50,380 Now, if you're looking at the menu, 501 00:22:50,380 --> 00:22:53,420 then over here we have also the relevant resources 502 00:22:53,420 --> 00:22:56,460 for the menu, but we also have here things 503 00:22:56,460 --> 00:22:59,100 for the sections and the items. 504 00:22:59,100 --> 00:23:02,180 If this starts growing and becomes a God file, 505 00:23:02,180 --> 00:23:04,300 then of course you can split this up further 506 00:23:04,300 --> 00:23:08,940 and create a menu sections or menu items and so on. 507 00:23:08,940 --> 00:23:11,060 So now that we have this, we can go back 508 00:23:11,060 --> 00:23:13,220 to the utilities class. 509 00:23:13,220 --> 00:23:18,220 Over here, we can now say constants dot host dot ID dot string. 510 00:23:19,700 --> 00:23:22,300 This will give us the host ID. 511 00:23:22,300 --> 00:23:26,300 Next, we can do the same thing, but over here say menu 512 00:23:26,300 --> 00:23:31,300 and choose the name and same thing for the description. 513 00:23:31,300 --> 00:23:33,620 The last thing we need to specify over here 514 00:23:33,620 --> 00:23:36,900 is the list of sections, okay? 515 00:23:36,900 --> 00:23:39,700 Now, this is where it usually goes wrong 516 00:23:39,700 --> 00:23:41,780 in most applications that I encounter 517 00:23:41,780 --> 00:23:44,100 and I want to propose something else 518 00:23:44,100 --> 00:23:46,900 and I hope that you'll apply this in your projects as well. 519 00:23:46,900 --> 00:23:49,140 So over here, we need to create a list of many sections. 520 00:23:49,140 --> 00:23:51,180 For that, let's create a new method 521 00:23:51,180 --> 00:23:56,180 that knows how to generate a list of menu sections 522 00:23:56,180 --> 00:23:58,980 based on the number of menu sections that we want. 523 00:23:58,980 --> 00:24:01,500 Let's actually copy this entire method, 524 00:24:01,500 --> 00:24:05,420 paste it over here and let's remove this 525 00:24:05,420 --> 00:24:09,780 and what this receives is also the number of sections 526 00:24:09,780 --> 00:24:10,700 that we want to create. 527 00:24:10,700 --> 00:24:12,820 So let's say section count 528 00:24:12,820 --> 00:24:16,020 and it will create the number of sections based on this count. 529 00:24:16,020 --> 00:24:17,300 So for that, we can do the following trick. 530 00:24:17,300 --> 00:24:19,300 We can say enumerable dot range. 531 00:24:19,300 --> 00:24:23,220 We can give it the range from zero until the section count 532 00:24:23,220 --> 00:24:26,180 and over here we can select 533 00:24:26,180 --> 00:24:29,820 and based on the index that we have, 534 00:24:29,820 --> 00:24:32,300 create a new menu section. 535 00:24:32,300 --> 00:24:37,300 So we can say over here, new menu section command 536 00:24:37,300 --> 00:24:41,980 and finally to list this entire thing and return it. 537 00:24:41,980 --> 00:24:45,380 Now to create a new menu section command, 538 00:24:45,380 --> 00:24:49,700 we want each one of the sections to be unique, 539 00:24:49,700 --> 00:24:51,180 meaning we don't want all of them 540 00:24:51,180 --> 00:24:53,700 to have the exact same name and description 541 00:24:53,700 --> 00:24:57,500 because that can cause bugs that we're not aware of 542 00:24:57,500 --> 00:24:59,820 because we're comparing two different items 543 00:24:59,820 --> 00:25:01,140 but they have the same name and description. 544 00:25:01,140 --> 00:25:03,660 So we think they're the same even though they are not. 545 00:25:03,660 --> 00:25:07,220 So what we can do in this case is a very neat trick. 546 00:25:07,220 --> 00:25:08,060 Let's do the following. 547 00:25:08,060 --> 00:25:11,980 Let's go to the menu constants and over here, 548 00:25:11,980 --> 00:25:13,940 let's create a new method 549 00:25:13,940 --> 00:25:18,940 that will know how to generate a new menu section name 550 00:25:18,940 --> 00:25:21,780 based on a given index, okay? 551 00:25:21,780 --> 00:25:24,340 Because it's very common when we have a list 552 00:25:24,340 --> 00:25:28,020 of menu sections that we'll want based on the index 553 00:25:28,020 --> 00:25:31,540 inside the list to have a unique name and description. 554 00:25:31,540 --> 00:25:33,860 So that's over here, public, static 555 00:25:33,860 --> 00:25:36,060 and then we want to create a section name 556 00:25:36,060 --> 00:25:38,900 from a given index. 557 00:25:38,900 --> 00:25:40,860 So let's say section name from index, 558 00:25:40,860 --> 00:25:43,980 let's give it over here the index that we're creating 559 00:25:43,980 --> 00:25:47,140 the section name for and what this will return 560 00:25:47,140 --> 00:25:51,580 is simply the section name that we have above 561 00:25:51,580 --> 00:25:53,460 and the index. 562 00:25:53,460 --> 00:25:57,780 Now we have something that's specific for this index name. 563 00:25:57,780 --> 00:26:00,060 Let's just specify the return type 564 00:26:00,060 --> 00:26:01,980 and maybe let's put this on a new line. 565 00:26:01,980 --> 00:26:03,420 So it's visible, okay? 566 00:26:03,420 --> 00:26:05,220 Now that we have this, then we can do the same thing 567 00:26:05,220 --> 00:26:09,180 for the section description and for the items. 568 00:26:09,180 --> 00:26:11,260 So I'll write it out and then we'll go over it. 569 00:26:11,260 --> 00:26:12,100 Alright, so here we have it. 570 00:26:12,100 --> 00:26:14,180 We can create section name and description 571 00:26:14,180 --> 00:26:18,060 and item name and description based on a given index 572 00:26:18,060 --> 00:26:19,380 having something unique. 573 00:26:19,380 --> 00:26:21,260 Now what we can do is we can go back 574 00:26:21,260 --> 00:26:23,460 to the test details over here and we can say 575 00:26:23,460 --> 00:26:26,660 the following each one of the sections again 576 00:26:26,660 --> 00:26:28,340 has a name and description. 577 00:26:28,340 --> 00:26:30,780 So for that, we can say the following, 578 00:26:30,780 --> 00:26:35,780 let's say constants.menu and then we want to get the section 579 00:26:36,980 --> 00:26:40,460 name from index and the index that we wanna give it 580 00:26:40,460 --> 00:26:41,860 is the current index. 581 00:26:41,860 --> 00:26:44,060 And we want to do the same thing for the description. 582 00:26:44,060 --> 00:26:46,580 So I'll say over here, description 583 00:26:46,580 --> 00:26:48,660 and this will give us what we want, okay? 584 00:26:48,660 --> 00:26:51,900 Now let's do the same thing for the menu items. 585 00:26:51,900 --> 00:26:55,140 Okay, so I wrote it out, same thing like we have over here 586 00:26:55,140 --> 00:26:57,540 but I replaced where it says section with item. 587 00:26:57,540 --> 00:26:59,700 Now one thing that I did notice is that this should be 588 00:26:59,700 --> 00:27:02,380 plural because we're creating multiple items 589 00:27:02,380 --> 00:27:04,500 and also the return type needs to be a list 590 00:27:04,500 --> 00:27:07,660 because again, we're turning a list of items. 591 00:27:07,660 --> 00:27:08,780 So let's do the same thing over here. 592 00:27:08,780 --> 00:27:11,780 Let's change the sections to sections. 593 00:27:11,780 --> 00:27:15,820 I changed this to be a list of menu section commands. 594 00:27:15,820 --> 00:27:19,220 And then over here, we can call the create items command 595 00:27:19,220 --> 00:27:22,060 and we need to specify here a section count. 596 00:27:22,060 --> 00:27:24,660 Let's say by default, when you don't specify a count, 597 00:27:24,660 --> 00:27:25,820 then the default is one. 598 00:27:25,820 --> 00:27:29,780 Let's do the same also over here. 599 00:27:29,780 --> 00:27:30,780 Great, so we have that. 600 00:27:30,780 --> 00:27:32,260 Let's align the parentheses. 601 00:27:32,260 --> 00:27:34,980 Let's to list this and now that we have 602 00:27:34,980 --> 00:27:38,180 two of these out of the way, we can get rid of this, 603 00:27:38,180 --> 00:27:40,980 rid of this and finally over here, 604 00:27:40,980 --> 00:27:44,740 we can call the create sections command 605 00:27:44,740 --> 00:27:47,340 which will create the list of sections, okay? 606 00:27:47,340 --> 00:27:51,100 Now because this can return null theoretically, 607 00:27:51,100 --> 00:27:54,820 so let's silence the compiler telling it, 608 00:27:54,820 --> 00:27:56,300 don't worry, this can't meet null. 609 00:27:56,300 --> 00:27:57,420 Now that we have all this written out, 610 00:27:57,420 --> 00:27:58,260 there are still some things 611 00:27:58,260 --> 00:27:59,940 that we're going to change here in a minute 612 00:27:59,940 --> 00:28:03,060 but now we have three components. 613 00:28:03,060 --> 00:28:04,780 One of them knows how to create the command, 614 00:28:04,780 --> 00:28:07,100 one of them knows how to create a list of sections 615 00:28:07,100 --> 00:28:09,900 and one of them knows how to create a list of items. 616 00:28:09,900 --> 00:28:11,580 Now let's go back over here 617 00:28:11,580 --> 00:28:14,100 and we can create a valid menu 618 00:28:14,100 --> 00:28:18,620 by saying over here that we have the create menu command 619 00:28:18,620 --> 00:28:22,380 equals the create menu command details 620 00:28:22,380 --> 00:28:25,780 and we want to simply call create command, okay? 621 00:28:25,780 --> 00:28:27,140 So we want this type of instruction 622 00:28:27,140 --> 00:28:29,340 where we simply call create command 623 00:28:29,340 --> 00:28:33,460 and behind the scenes it creates the corresponding command 624 00:28:33,460 --> 00:28:37,220 in a valid way without us having to do it manually 625 00:28:37,220 --> 00:28:39,660 inside our test, reducing the cognitive load 626 00:28:39,660 --> 00:28:41,060 of anyone looking at the test, 627 00:28:41,060 --> 00:28:43,940 simply saying this, okay great, this creates the command, 628 00:28:43,940 --> 00:28:45,220 what happens next, okay? 629 00:28:45,220 --> 00:28:46,940 So now that we have this out of the way, 630 00:28:46,940 --> 00:28:48,180 the next thing that we want to do 631 00:28:48,180 --> 00:28:50,700 is we want to invoke the handler. 632 00:28:50,700 --> 00:28:53,740 All I did was create a new instance of the command handler. 633 00:28:53,740 --> 00:28:54,940 So if we're looking over here, 634 00:28:54,940 --> 00:28:57,580 then we're simply calling the constructor over here 635 00:28:57,580 --> 00:29:00,580 and we still need to specify the menu repository. 636 00:29:00,580 --> 00:29:02,980 For that I'm going to use mock the library 637 00:29:02,980 --> 00:29:04,460 for mocking objects. 638 00:29:04,460 --> 00:29:06,220 I'm assuming you all know already the theory behind it. 639 00:29:06,220 --> 00:29:09,060 So I'll write it out and then we'll cover it briefly. 640 00:29:09,060 --> 00:29:11,940 So we're going to add the package mock. 641 00:29:11,940 --> 00:29:14,660 This will add the library that we need 642 00:29:14,660 --> 00:29:17,660 and then we can go ahead and create here the repository. 643 00:29:17,660 --> 00:29:20,620 Okay, now I do want to say that I like the prefix of mock 644 00:29:20,620 --> 00:29:22,780 for mock objects because again, 645 00:29:22,780 --> 00:29:24,980 it reduces the cognitive load of looking at each one 646 00:29:24,980 --> 00:29:26,580 of the objects and trying to understand 647 00:29:26,580 --> 00:29:28,380 if it's the actual concrete object 648 00:29:28,380 --> 00:29:30,620 or if it's a mock of that object. 649 00:29:30,620 --> 00:29:32,020 Okay, so now that we have this, 650 00:29:32,020 --> 00:29:35,220 let's go ahead and invoke it below in the test. 651 00:29:35,220 --> 00:29:39,500 So that's over here that the result equals 652 00:29:39,500 --> 00:29:42,420 and over here we want to await calling the command handler 653 00:29:42,420 --> 00:29:43,820 because it's asynchronous. 654 00:29:43,820 --> 00:29:47,700 So let's say over here, I sync task and over here, 655 00:29:47,700 --> 00:29:51,300 let's say that we want to call the handle method 656 00:29:51,300 --> 00:29:55,460 and over here we want to pass it the create menu command 657 00:29:55,460 --> 00:29:57,180 and for the cancellation token, 658 00:29:57,180 --> 00:29:59,180 that's simply pass default. 659 00:29:59,180 --> 00:30:01,860 Now that we have the result from the method, 660 00:30:01,860 --> 00:30:05,300 what we want to make sure is that the correct menu aggregate 661 00:30:05,300 --> 00:30:08,220 was created based on the create menu command 662 00:30:08,220 --> 00:30:12,340 and also that the menu was indeed added to the repository. 663 00:30:12,340 --> 00:30:15,580 Now, because what this returns is an error 664 00:30:15,580 --> 00:30:17,740 or the menu aggregate, 665 00:30:17,740 --> 00:30:20,100 so the first thing we want to do is we want to make sure 666 00:30:20,100 --> 00:30:21,740 that it is not an error. 667 00:30:21,740 --> 00:30:24,020 So for this, we're going to use fluent assertions. 668 00:30:24,020 --> 00:30:27,180 So for this, let's simply add fluent assertions 669 00:30:27,180 --> 00:30:30,380 and now we can simply say should be false. 670 00:30:30,380 --> 00:30:32,540 And next thing we want to do is we want to validate 671 00:30:32,540 --> 00:30:35,500 the values in the menu that they were constructed 672 00:30:35,500 --> 00:30:39,380 according to the values that we specified in the command. 673 00:30:39,380 --> 00:30:43,660 Now to do this, again, we want to build it in a way 674 00:30:43,660 --> 00:30:47,780 that as the application grows more validation methods 675 00:30:47,780 --> 00:30:48,780 like what we're going to write. 676 00:30:48,780 --> 00:30:51,580 Now, we're going to sit in a single place 677 00:30:51,580 --> 00:30:55,260 so it's easy to refactor or change as the application grows. 678 00:30:55,260 --> 00:30:56,820 So for that, what I really like doing 679 00:30:56,820 --> 00:30:58,420 is creating extension methods 680 00:30:58,420 --> 00:31:00,900 because again, it reduces the cognitive load 681 00:31:00,900 --> 00:31:03,260 when I simply want to make sure 682 00:31:03,260 --> 00:31:06,980 that the menu was created from the command. 683 00:31:06,980 --> 00:31:08,540 Then all I can write is the following. 684 00:31:08,540 --> 00:31:12,220 You can say result.value, which is the underlying menu. 685 00:31:12,220 --> 00:31:15,100 And I can say validate created from 686 00:31:15,100 --> 00:31:18,380 and pass it over here, the command as so. 687 00:31:18,380 --> 00:31:20,300 So let's write this extension method 688 00:31:20,300 --> 00:31:22,580 which will have inside all the logic 689 00:31:22,580 --> 00:31:25,300 that has to do with validating the value. 690 00:31:25,300 --> 00:31:27,060 So for that, let's create here a new folder 691 00:31:27,060 --> 00:31:28,740 and let's call it menus. 692 00:31:28,740 --> 00:31:30,660 And over here, we'll create another folder, 693 00:31:30,660 --> 00:31:31,860 let's call it extensions. 694 00:31:31,860 --> 00:31:34,500 And what we'll have over here is again, 695 00:31:34,500 --> 00:31:38,420 multiple files with extensions on the menu area 696 00:31:38,420 --> 00:31:41,740 so that we don't have in extensions God file 697 00:31:41,740 --> 00:31:44,740 that contains all the various extensions that we might have. 698 00:31:44,740 --> 00:31:49,420 So I'd say menu extensions dot validations dot CS. 699 00:31:49,420 --> 00:31:50,900 So I wrote out the validation logic 700 00:31:50,900 --> 00:31:54,020 and what we have here is the following. 701 00:31:54,020 --> 00:31:57,140 So we have a method that receives both the menu 702 00:31:57,140 --> 00:32:01,140 and the command and it goes through all the various properties 703 00:32:01,140 --> 00:32:04,860 and validates that the correct value from the command 704 00:32:04,860 --> 00:32:08,740 was assigned to the correct value in the menu. 705 00:32:08,740 --> 00:32:11,660 Now a small trick that you can do, if you're not aware of it, 706 00:32:11,660 --> 00:32:13,460 is that if you have two lists 707 00:32:13,460 --> 00:32:16,140 and you want to take the pairs of them by index 708 00:32:16,140 --> 00:32:19,140 and make sure that they have the same values, 709 00:32:19,140 --> 00:32:20,700 then instead of doing a for loop 710 00:32:20,700 --> 00:32:23,260 where you're creating an index and then you read 711 00:32:23,260 --> 00:32:26,860 from the list and that specific index in both of the lists, 712 00:32:26,860 --> 00:32:28,860 then you can simply zip them together. 713 00:32:28,860 --> 00:32:32,780 So in our case, we're zipping the menu sections 714 00:32:32,780 --> 00:32:34,180 and the command sections. 715 00:32:34,180 --> 00:32:35,660 And over here we have a pair 716 00:32:35,660 --> 00:32:38,780 where we have them, the corresponding pairs 717 00:32:38,780 --> 00:32:40,980 within the two lists and then we can compare them. 718 00:32:40,980 --> 00:32:42,900 So that's just a nice trick that if you're not using 719 00:32:42,900 --> 00:32:45,260 and you like it, then you can consider using. 720 00:32:45,260 --> 00:32:46,100 Okay, so now that we have this, 721 00:32:46,100 --> 00:32:48,460 let's go back to our test method. 722 00:32:48,460 --> 00:32:51,900 This validates created from method now exists. 723 00:32:51,900 --> 00:32:53,020 What I like about this approach 724 00:32:53,020 --> 00:32:55,740 is that we have the good type of abstraction 725 00:32:55,740 --> 00:32:59,540 where I don't care about how this thing is constructed, 726 00:32:59,540 --> 00:33:03,440 but I know I have over here a valid create menu command. 727 00:33:03,440 --> 00:33:05,460 And over here, I'm validating 728 00:33:05,460 --> 00:33:07,460 that it was constructed correctly. 729 00:33:07,460 --> 00:33:08,500 The last thing that we're missing 730 00:33:08,500 --> 00:33:11,420 is making sure that the menu repository 731 00:33:11,420 --> 00:33:13,660 was called with the exact same menu. 732 00:33:13,660 --> 00:33:16,380 So for that, all we need to do is we can say mock 733 00:33:16,380 --> 00:33:19,100 the menu repository and we want to verify 734 00:33:19,100 --> 00:33:23,140 that the add async method was called specifically 735 00:33:23,140 --> 00:33:27,420 with the menu that was returned from the method 736 00:33:27,420 --> 00:33:31,100 and we want to make sure that it was called exactly once. 737 00:33:31,100 --> 00:33:32,660 Okay, so we have that, it's starting to look good, 738 00:33:32,660 --> 00:33:35,340 but what if this specific create menu command 739 00:33:35,340 --> 00:33:39,300 is valid and it runs through the test successfully, 740 00:33:39,300 --> 00:33:42,660 but other variations that are also valid 741 00:33:42,660 --> 00:33:44,260 of the command don't run successfully, right? 742 00:33:44,260 --> 00:33:45,780 So we're not covering those cases. 743 00:33:45,780 --> 00:33:47,220 So what I want to do is extract this 744 00:33:47,220 --> 00:33:50,500 and put different variations of valid menus. 745 00:33:50,500 --> 00:33:52,900 And then we have this single test 746 00:33:52,900 --> 00:33:56,620 that's testing all the various valid menu commands. 747 00:33:56,620 --> 00:33:58,380 So what we're going to do for that is we're going 748 00:33:58,380 --> 00:33:59,220 to do the following. 749 00:33:59,220 --> 00:34:00,660 So let's say over here theory 750 00:34:00,660 --> 00:34:04,740 and over here we're going to create a member data 751 00:34:04,740 --> 00:34:07,060 where over here we're going to have a method 752 00:34:07,060 --> 00:34:09,820 that will create multiple valid menus. 753 00:34:09,820 --> 00:34:14,100 So that's over here, valid create menu commands 754 00:34:14,100 --> 00:34:17,100 and let's generate this method. 755 00:34:17,100 --> 00:34:19,420 And what this is going to return is, 756 00:34:19,420 --> 00:34:21,020 as you probably already know, 757 00:34:21,020 --> 00:34:25,900 this needs to return and I am numerable of type list 758 00:34:25,900 --> 00:34:29,620 of objects and to get rid of this squiggly line. 759 00:34:29,620 --> 00:34:31,460 Let's say we're here that here we have 760 00:34:31,460 --> 00:34:33,380 the create menu command, right? 761 00:34:33,380 --> 00:34:38,380 So let's take this thing and paste it over here 762 00:34:38,380 --> 00:34:41,260 and now we can remove this entire thing. 763 00:34:41,260 --> 00:34:44,580 We still have a squiggly line and that's because 764 00:34:44,580 --> 00:34:47,660 this should be public and static. 765 00:34:47,660 --> 00:34:49,660 So now that we have that, great. 766 00:34:49,660 --> 00:34:50,740 Now what we want to do over here 767 00:34:50,740 --> 00:34:54,060 is return multiple valid menus. 768 00:34:54,060 --> 00:34:56,260 So what I removed from over here, 769 00:34:56,260 --> 00:34:59,140 let's paste it back inside this method. 770 00:34:59,140 --> 00:35:00,020 So let's say over here, 771 00:35:00,020 --> 00:35:03,580 yield return and over here we want to create a new list 772 00:35:03,580 --> 00:35:06,500 of objects where what we're doing is calling 773 00:35:06,500 --> 00:35:11,500 the create menu command you tilt and create command. 774 00:35:11,500 --> 00:35:14,740 This thing and this will be similar to what we wrote before. 775 00:35:14,740 --> 00:35:17,780 So we have this but we also would like different cases 776 00:35:17,780 --> 00:35:21,140 where let's say over here we have three sections 777 00:35:21,140 --> 00:35:22,940 and another one where we have three sections 778 00:35:22,940 --> 00:35:26,100 and each one of the sections has also three items. 779 00:35:26,100 --> 00:35:27,940 Now to test that case, 780 00:35:27,940 --> 00:35:31,180 what we want to do is update these methods 781 00:35:31,180 --> 00:35:34,540 to be a bit more flexible where we can update the way 782 00:35:34,540 --> 00:35:36,180 the command is constructed. 783 00:35:36,180 --> 00:35:37,620 I want to encourage you to pause the video, 784 00:35:37,620 --> 00:35:39,340 look at the details class that we have over here 785 00:35:39,340 --> 00:35:43,340 and think how you would update the methods over here 786 00:35:43,340 --> 00:35:46,140 to support creating a create many command 787 00:35:46,140 --> 00:35:49,660 where we have a custom number of sections 788 00:35:49,660 --> 00:35:51,540 and a custom number of items 789 00:35:51,540 --> 00:35:55,860 when creating the create command method over here. 790 00:35:55,860 --> 00:35:58,740 So the wrong answer in my opinion is saying over here, 791 00:35:58,740 --> 00:36:01,780 let's pass the section count and the item count 792 00:36:01,780 --> 00:36:04,700 and then we need to pass over here the two counts down 793 00:36:04,700 --> 00:36:07,860 and then pass the item count down to here. 794 00:36:07,860 --> 00:36:11,740 Instead, what I like doing and I think is more scalable. 795 00:36:11,740 --> 00:36:13,660 Again, we want small building blocks 796 00:36:13,660 --> 00:36:17,460 that as application grows and we have more and more variations 797 00:36:17,460 --> 00:36:18,780 of this create command, 798 00:36:18,780 --> 00:36:21,260 the parameters over here doesn't become a list 799 00:36:21,260 --> 00:36:24,340 of 100 parameters where then you have edge cases 800 00:36:24,340 --> 00:36:26,500 where you say, oh, maybe I'll just pass here a Boolean 801 00:36:26,500 --> 00:36:29,100 and then if it's true, then I'll do this 802 00:36:29,100 --> 00:36:30,860 and if it's false, then I'll create the object 803 00:36:30,860 --> 00:36:33,860 in a different way because then this becomes 804 00:36:33,860 --> 00:36:36,180 a God method of creating the command. 805 00:36:36,180 --> 00:36:39,180 Instead, what I suggest is the following. 806 00:36:39,180 --> 00:36:42,620 So over here, we'll call the create sections command 807 00:36:42,620 --> 00:36:46,500 only if the user didn't specify a list of sections. 808 00:36:46,500 --> 00:36:51,220 So that's a list of create menu section command 809 00:36:51,220 --> 00:36:52,860 and this is going to be optional 810 00:36:52,860 --> 00:36:55,220 and we're going to say sections 811 00:36:55,220 --> 00:36:59,220 and if we didn't specify sections, 812 00:36:59,220 --> 00:37:04,220 then we'll create the basic sections as we had before. 813 00:37:04,220 --> 00:37:07,420 So this still works like it worked before. 814 00:37:07,420 --> 00:37:10,540 What's nice about this is that now we can do the following. 815 00:37:10,540 --> 00:37:12,940 Let's call the create command, 816 00:37:12,940 --> 00:37:15,820 but now we can specify the sections over here. 817 00:37:15,820 --> 00:37:19,140 So we can say this thing sections command 818 00:37:19,140 --> 00:37:23,140 and specify here that the section count is three, 819 00:37:23,140 --> 00:37:27,060 like we said before, let's just add a trailing comma over here 820 00:37:27,060 --> 00:37:29,100 and that's it, okay? 821 00:37:29,100 --> 00:37:31,140 Now the same thing for the items. 822 00:37:31,140 --> 00:37:35,340 So let's say we want to create another one over here 823 00:37:35,340 --> 00:37:38,780 where this time we have a custom list of items. 824 00:37:38,780 --> 00:37:40,460 So going through the exact same logic, 825 00:37:40,460 --> 00:37:43,220 let's say over here that other than the section count, 826 00:37:43,220 --> 00:37:47,020 it can also receive an optional list of items. 827 00:37:47,020 --> 00:37:51,220 So let's simply copy this thing over here, 828 00:37:51,220 --> 00:37:54,100 paste it down here where it says section. 829 00:37:54,100 --> 00:37:57,780 Let's replace it with item, let's say items 830 00:37:57,780 --> 00:38:01,900 and let's say that if we didn't specify items, 831 00:38:01,900 --> 00:38:06,100 then it's going to call the create menu command. 832 00:38:06,100 --> 00:38:09,660 Okay, so again, when constructing complex objects, 833 00:38:09,660 --> 00:38:14,620 then we define optional parameters with the inner objects. 834 00:38:14,620 --> 00:38:16,100 And then if they're not specified, 835 00:38:16,100 --> 00:38:19,340 then we create some default, otherwise we use them. 836 00:38:19,340 --> 00:38:21,820 This is true for the inner objects as well. 837 00:38:21,820 --> 00:38:24,420 So for the section, then also over here, 838 00:38:24,420 --> 00:38:27,100 we receive the optional list of items. 839 00:38:27,100 --> 00:38:31,180 And if it wasn't specified, then we create it over here. 840 00:38:31,180 --> 00:38:32,580 Okay, so now that we have this, 841 00:38:32,580 --> 00:38:37,580 then we can go ahead and say that the section count is three, 842 00:38:37,580 --> 00:38:41,780 but the items isn't the default, 843 00:38:41,780 --> 00:38:44,740 but we want to create our custom item. 844 00:38:44,740 --> 00:38:47,740 So let's say over here, create items command 845 00:38:47,740 --> 00:38:51,580 and let's specify the item count, item count. 846 00:38:51,580 --> 00:38:52,940 It's already called it section count. 847 00:38:52,940 --> 00:38:55,980 Let's change this to be item count. 848 00:38:55,980 --> 00:38:58,940 So let's pass it the item count, which is three. 849 00:38:58,940 --> 00:39:01,740 Like we said, we're building a small testing framework 850 00:39:01,740 --> 00:39:04,900 for our specific domain or application. 851 00:39:04,900 --> 00:39:08,540 And now what we have is we still have the create command, 852 00:39:08,540 --> 00:39:12,860 which is generic and everything else stays generic as well. 853 00:39:12,860 --> 00:39:16,260 So now when we want to test creating an invalid menu, 854 00:39:16,260 --> 00:39:19,460 then all we need to do is follow the same logic 855 00:39:19,460 --> 00:39:21,460 for the name of the description. 856 00:39:21,460 --> 00:39:25,420 And then for example, if you want to create an invalid menu 857 00:39:25,420 --> 00:39:27,700 where the name is invalid, then all we need to do 858 00:39:27,700 --> 00:39:30,460 is define the name as a parameter as well. 859 00:39:30,460 --> 00:39:32,460 Then if the name was specified, then we use that. 860 00:39:32,460 --> 00:39:34,420 Otherwise we fall back to the default 861 00:39:34,420 --> 00:39:38,780 and we follow the same logic building small building blocks 862 00:39:38,780 --> 00:39:41,780 throughout our unit test project. 863 00:39:41,780 --> 00:39:43,340 Now I'm saying unit test project, 864 00:39:43,340 --> 00:39:46,300 but of course, many of this can apply 865 00:39:46,300 --> 00:39:49,300 to any other test project that you're created. 866 00:39:49,300 --> 00:39:52,980 I want you to take the idea of breaking down 867 00:39:52,980 --> 00:39:55,060 whatever code in the unit test project 868 00:39:55,060 --> 00:39:58,060 that you're writing, breaking it down into smaller components 869 00:39:58,060 --> 00:40:00,580 so as the application grows, it grows horizontally. 870 00:40:00,580 --> 00:40:04,020 So we're adding more files with specific logic 871 00:40:04,020 --> 00:40:07,140 instead of growing vertically where you have a single file 872 00:40:07,140 --> 00:40:10,020 that more and more methods are added. 873 00:40:10,020 --> 00:40:12,260 The reason why I like this approach 874 00:40:12,260 --> 00:40:14,460 is because now when we need to do the same thing 875 00:40:14,460 --> 00:40:16,460 for the create dinner command, 876 00:40:16,460 --> 00:40:18,460 then whoever's going to implement that, 877 00:40:18,460 --> 00:40:19,740 we'll take a look at this 878 00:40:19,740 --> 00:40:22,180 and we'll probably copy paste this code, 879 00:40:22,180 --> 00:40:24,620 change where it says menu to dinner 880 00:40:24,620 --> 00:40:27,060 and put the same logic over there, 881 00:40:27,060 --> 00:40:30,100 maintaining the same code structure 882 00:40:30,100 --> 00:40:35,020 in the future tests or test utilities that will be written. 883 00:40:35,020 --> 00:40:36,660 So we have our single test method. 884 00:40:36,660 --> 00:40:40,540 Maybe let's remove all these redundant comments. 885 00:40:40,540 --> 00:40:44,180 Let's put a break point over here and over here 886 00:40:44,180 --> 00:40:47,420 and actually also in the command handler. 887 00:40:47,420 --> 00:40:49,340 Let's put a break point over here. 888 00:40:49,340 --> 00:40:50,300 Okay, so we hit the break point 889 00:40:50,300 --> 00:40:51,580 and first of all, let's make sure 890 00:40:51,580 --> 00:40:54,140 that this create many command was constructed 891 00:40:54,140 --> 00:40:54,980 like we expect. 892 00:40:54,980 --> 00:40:58,780 So looking at the name, the description and the host ID, 893 00:40:58,780 --> 00:41:01,660 it looks yes as we defined and looking at the sections. 894 00:41:01,660 --> 00:41:04,940 So we have one section and this one section that we have 895 00:41:04,940 --> 00:41:07,860 has the section name and description 896 00:41:07,860 --> 00:41:11,260 with the index appended to the end 897 00:41:11,260 --> 00:41:12,340 and when it comes to the items 898 00:41:12,340 --> 00:41:13,580 and then we have the exact same thing 899 00:41:13,580 --> 00:41:16,060 with zero appended to the end. 900 00:41:16,060 --> 00:41:17,200 Great, so this looks as we expect. 901 00:41:17,200 --> 00:41:19,260 Let's continue and we hit the break point 902 00:41:19,260 --> 00:41:21,180 inside the command handler. 903 00:41:21,180 --> 00:41:23,780 Let's step over this and we create it. 904 00:41:23,780 --> 00:41:27,980 The menu aggregate based on the values that we specified. 905 00:41:27,980 --> 00:41:31,060 So we can see over here that indeed we have 906 00:41:31,060 --> 00:41:35,500 the correct values that correspond to the command 907 00:41:35,500 --> 00:41:37,900 that we passed, we're calling the add us sync 908 00:41:37,900 --> 00:41:39,460 and because this is a mocked object 909 00:41:39,460 --> 00:41:41,140 and we didn't define a behavior, 910 00:41:41,140 --> 00:41:42,980 then nothing happens over there 911 00:41:42,980 --> 00:41:46,780 other than registering the call was made. 912 00:41:46,780 --> 00:41:48,700 So we're returning the menu over here. 913 00:41:48,700 --> 00:41:51,580 We have the is error, the is error is indeed false. 914 00:41:51,580 --> 00:41:54,740 In the value we have, like we said, the menu aggregate. 915 00:41:54,740 --> 00:41:57,260 If we step into this, then we run 916 00:41:57,260 --> 00:41:58,580 through the various validations 917 00:41:58,580 --> 00:42:00,420 and make sure that all the various values 918 00:42:00,420 --> 00:42:01,900 were assigned correctly. 919 00:42:01,900 --> 00:42:03,740 And finally, we want to make sure 920 00:42:03,740 --> 00:42:05,300 that the add us sync was called 921 00:42:05,300 --> 00:42:08,420 with the exact value that we specified 922 00:42:08,420 --> 00:42:09,780 and that it was called only once. 923 00:42:09,780 --> 00:42:12,900 So continuing and when we run through this again, 924 00:42:12,900 --> 00:42:14,860 then now we should have the create many command 925 00:42:14,860 --> 00:42:17,100 and this time it has three sections 926 00:42:17,100 --> 00:42:19,380 but one item per section. 927 00:42:19,380 --> 00:42:21,020 And this is indeed what we have 928 00:42:21,020 --> 00:42:22,580 and we want to make sure that the name 929 00:42:22,580 --> 00:42:26,580 really is unique based on the index of the section. 930 00:42:26,580 --> 00:42:27,780 Okay, so let's click continue. 931 00:42:27,780 --> 00:42:31,220 I think you got the idea, let's run until the end. 932 00:42:31,220 --> 00:42:33,860 Okay, so the tests pass successfully. 933 00:42:33,860 --> 00:42:36,420 So overall, what we have is the following. 934 00:42:36,420 --> 00:42:40,260 We have the tests file that sits in the same hierarchy 935 00:42:40,260 --> 00:42:42,980 based on the source code that it's testing. 936 00:42:42,980 --> 00:42:45,260 Then we have a test utils that sits 937 00:42:45,260 --> 00:42:48,260 as close to the code that uses it as possible. 938 00:42:48,260 --> 00:42:51,660 So if this now is used by other components 939 00:42:51,660 --> 00:42:54,340 that are outside of the commands folder, 940 00:42:54,340 --> 00:42:58,660 then we'll take it up to the next folder in the hierarchy. 941 00:42:58,660 --> 00:43:01,540 Then we have the general test utils 942 00:43:01,540 --> 00:43:03,980 that are used across the entire test project. 943 00:43:03,980 --> 00:43:06,180 And inside here, we're trying to break it up 944 00:43:06,180 --> 00:43:09,540 into smaller components so that each one of the files 945 00:43:09,540 --> 00:43:11,540 doesn't become a God file. 946 00:43:11,540 --> 00:43:13,860 Lastly, we have creating complex objects 947 00:43:13,860 --> 00:43:17,540 where we pass the inner objects or properties 948 00:43:17,540 --> 00:43:21,500 as parameters instead of passing the logic 949 00:43:21,500 --> 00:43:24,700 that we want for the inner object construction 950 00:43:24,700 --> 00:43:27,340 as part of the parameters of this method. 951 00:43:27,340 --> 00:43:31,140 So we don't want any logic that has to do with sections 952 00:43:31,140 --> 00:43:35,580 passed as a argument to the create command method. 953 00:43:35,580 --> 00:43:36,920 Okay, so I hope that makes sense. 954 00:43:36,920 --> 00:43:39,740 You learned something new and that you already see places 955 00:43:39,740 --> 00:43:41,780 in your application where you can apply it. 956 00:43:41,780 --> 00:43:44,780 If you disagree with anything that I wrote, 957 00:43:44,780 --> 00:43:47,940 then of course, don't do it in your application. 958 00:43:47,940 --> 00:43:50,700 This is definitely up for preference, 959 00:43:50,700 --> 00:43:53,660 but do let me know in the comments what you like to do 960 00:43:53,660 --> 00:43:55,320 and if you like doing it otherwise, 961 00:43:55,320 --> 00:43:57,460 because I think it will start some very interesting 962 00:43:57,460 --> 00:44:00,100 conversations between different projects 963 00:44:00,100 --> 00:44:01,620 that have different patterns. 964 00:44:01,620 --> 00:44:03,300 So I'm curious to hear what you think. 965 00:44:03,300 --> 00:44:04,340 Let me know in the comments. 966 00:44:04,340 --> 00:44:07,740 And if you enjoyed it, don't forget to hit the like button, 967 00:44:07,740 --> 00:44:11,340 smash the subscribe button and I'll see you in the next one.