REFACTORING UNIT TESTS in ASP NET Core | Getting Started With ASP.NET Core Series

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
writing test is hard and writing maintainable and robust tests is even harder one of the things that i have always struggled with and i've also seen many teams struggle with is writing maintainable tests anytime we make a change in the source code it breaks a bunch of tests like we try clean coding practices in our production code we should also be trying to keep our test clean in this video i will show you some of the libraries and patterns that i use when writing test which makes it more maintainable and robust hello everyone welcome to this youtube channel and my name is rahul if you're new here i make videos on dotnet cloud and devops i'm sure one of this is interest to you so make sure to hit subscribe if you find this video useful without much delay let's head off straight to refactoring test here i have the microsoft documentation on unit testing controller logic in asp.net core this has a sample application available here which i will be using as the baseline for the test refactoring that i'm going to do this source code is very concise and short which is why i chose to use this as my example for refactoring we will walk through this code see the existing test see some of the problems that exist and then try to refactor it into a more maintainable testing suit the patterns of test in this code is very similar and common across most of the applications that i have seen this might be something that you are doing today as well so let's see how we can change them slightly better i have the source code downloaded so if you go to this link you can see a github repository which is pointing to a specific folder now this repository has a lot more code in it so i have used the 3.x testing controller sample and downloaded it into my local folder now if i navigate there i have a similar structure and i have added a solution file to make it easy to load in the ide now i'll try and make short comments as and when we make changes so that you can look through it when you want to in this repository i will push the updated refactored repository onto my account so that you can take a look once this is all done i have the solution already opened up in the ide so let's navigate to that in rider so here we have the testing controller sample and the controller sample dot test project inside the sample project we have controllers which is the home and sessions controller under the test project we have three unit test classes which is api ids controller home controller and session controller test the api controller is under the api folder in this source code so if we navigate to the unit test and run them there's around 16 tests currently in this solution so let's go through them and understand some of the problems and see how we can fix them so all of them are currently running successfully so i'll be just refactoring the test which means all of them should still run successfully let's first navigate to the api ids controllers and see what we have there so let me expand all this code so let me go to folding and say expand all so we have a lot of test inside here which is using the x unit testing framework which is why we have the fact attribute inside here and also it uses the moq for mocking now if you're not familiar with this these are basically mock libraries and also x unit is a testing library in your application you might be using n unit or similar testing packages now the patterns that we use is not restricted to just x unit so you could still watch this and benefit from it so let's navigate to one of these tests where we have the ids controller and we pass this with a mock i brainstorm session repository now this is where we're using moq to mock this particular instance because we are not connecting with the real repository but with the marked instance of that so whenever we're creating the ids controller we create this mock instance and pass the object into this now let's say with the ids controller class let's navigate to that and see if we will be adding an i logger because we want to start logging inside this class so let's make sure to take in an i logger and specify the category type in this it'll be ids controller and we can say logger for now i'll simply use a backing field so let me create a read-only field inside this i'll not be committing this change because this is just for representation purposes let's make sure that this angle bracket is in the correct place and now build this again all our test that is using the ids controller is now broken this is because if we navigate to there we can see we are directly creating an ids controller inside our test object so now this is structurally dependent on how the constructor or the object is getting created now for all these tests i'll have to navigate and add in an i logger let's see a few other problems that we have with this code so let's navigate back to i logger undo this change of logger and come back to our api test inside here if we scroll down we can see we are setting up some test data manually on these classes now these values are nothing of concern to us but just dummy data and you can see the arrange phase has a lot of steps inside of here we will see how we can fix that as well now there's also this get test session object which is getting created to create a brainstorming session this is again a dummy data which we really don't care about now the same code is also duplicated in all of these other classes so if you go into the other one you can see similar methods to generate test sessions now you could extract this out into a helper library and use it from there as well but in this particular code base it is currently duplicated across all the classes so let's see how we can fix some of these issues that we are seeing and that we face when we write test to start with i will be using the auto fixture library which is to generate test data now if you're not familiar with auto fixture order fixture is a library that's for dot net which enables us to write maintainable unit test very fast auto fixture is designed to make test driven development more productive and riding unit test more refactoring safe if you're familiar with test builder pattern this is a generic way of creating test data as well it also provides various other features which we will see in this particular video now if you want to learn in depth of the different ways auto fixture can be used please check out my series linked here which has a few videos to get started with but as and when we use some feature i'll try and explain it in detail in this video as well so let's go and add an auto fixture nuget package to this test project so let's right click say manage new get packages and search for auto fixture you can see here we have the auto fixture you get and also we have the autofixture.x unit library this integrates with the x unit framework but if you're using n unit it also has an integration with the n unit now personally my preference is always to use x unit because i find it quite flexible and powerful when writing test most of the projects in fact all of the projects that i work on i try to make sure we are on x unit so let's go and add in the order fixture and the autofixture.x unit to this project so let's select that and click the plus button and install let's do the same with autofixture.xunit2 as well so we have both these packages installed to this test project now let's start using that so if you navigate back into api controller test let's close all the other ones and navigate to the place where we were hard coding some of the test data now inside here you can see we have test session test name test description which all three are used to create the new idea model so we have those properties being set appropriately on this model object we are then using this model object to do some action on the controller we also verify that the test name and test description is matching once we get back now since we are really not bothered about what values comes into these properties let's go and use this and generate it from auto fixture to start doing that let's first make this as a theory attribute now to start using order fixture i can say an auto data attribute which is what integrates with auto fixture let's first see how to use this and then i'll explain what is happening so let's copy this new idea model and make sure to inject this from the parameter inside the test so i can say new idea in here now let's remove this existing class which is no longer required once we remove that we can also remove these three properties which is unnecessarily getting defined now if you look at this we have a setup face on the mock repo to return this particular test session so this test session id can be used from new idea dot session id because that needs to be the same so whenever on the mock we are looking by this id we return back a specific test session which is also being set up in this method here now if we scroll down we expect the test name which is now coming from new idea dot name to be same as this value coming from the controller let's also update the test description which is going to be new idea dot description now we have updated all the tests without any errors so let's put a break point to see what is happening so let's click this and click debug the breakpoint is successfully hit so let's hover over a new idea to see what values it has if you look at this we can see this has random values being generated automatically so what autofixture does is for string properties it chooses the name and appends with a new good value so you can see there is the name and also a good value similarly for this name we have the property name which is also appended by a guide value for integers it generates a random integer so auto fixture has automatically generated random values for us for this particular model so now if we go back we can start using this model inside our test so i have the session id and these values being used exactly from the model that we are using for the test so if i run this it will work successfully now this integration is possible because of the auto data attribute that we added this is where it integrates with the fixture class and generates these objects automatically by doing this we have removed a lot of code which was unnecessary and which we really didn't care about because those properties were just having dummy values so let's make sure to remove these extra spaces and we have the arrange act and assert phase again so let's switch over to the command line and commit these changes so let's commit all these files because the cs project we added the nuget files and the changes to the test itself so let's say git commit minus m and say added the first autodata attribute now if we scroll up we can see similar examples where we are using these dummy values so we can now simply change this remove all that copy this new idea model make this a theory and also add in the auto data attribute and pass in this through the function parameter so let's say new idea and also delete this class inside of here once that's done it looks like everything is working fine in this particular case so let's run this to make sure we haven't broken anything that test is also passing successfully so let's scroll up to see if there is any similar instances where we can change that so up on this method create returns newly create idea for session we can still do the same so instead of using the new idea model we pass it through the function specify new idea instead of the fact we need to use theory because it has a parameter so fact is used whenever you don't have any parameter on the test and theory is used when you have parameters so let's go back and make sure to add the autodata attribute and remove all this code because that's not required anymore we can also delete these three lines because that's also just dummy data so like before we can say new idea dot session id and use that inside our mock setup for the test name we can say new idea dot name and for the description we can similarly use new idea dot description let's run this to make sure this is still working as expected now all the tests are still running successfully so let's navigate back let's add in all those files so make sure we are adding the same test file and commit this again so that you can use this for reference updated a few more of the new idea model now if you're wondering of this clipboard you can use windows and v to open this clipboard manager now this is a feature that someone has asked me on the comments so let's make sure to commit this and clear the screen again so let's navigate back now let's see how we can get rid of this get test session if we navigate to this method we can see we are creating a brainstorm session class inside of here now this dummy data is also something we are not interested in you can also see after creating the session we call the idea method and add a new idea so this session has an idea automatically added to it so let's navigate back to this test and start seeing if we can inject in the brainstorming session similarly so let's say brainstorming session and call this as test session itself to make this built successfully let's remove this line where we are getting the test session let's debug this and see what is happening as before with the new idea we have all these properties being set to random values let's look at test session which is also having random values set now if we look at the date created it has a random date similarly with id and name but note the ideas collection is empty inside of this particular session this is because inside of brainstorming session if we navigate to the class the list of ideas is a get only property so this is getting populated only by this add method now currently the brainstorming session cannot be loaded with an existing list of ideas i'll have to iterate through and call each of the ad idea but in this code this works because it uses entity framework which uses reflection magic to populate these properties i have written about these in a separate blog post which will be linked here and also in the description below but for now let's work under these constraints and see how we can get an idea added to the brainstorming session so if we navigate back to the idea controller test you can remember inside the get sessions method we had manually added an idea using the add idea method so let's see we can do something similar with auto fixture so let's stop this and first create a new class so let's navigate to the test folder i'll use the shortcut to create a new class i'll name this as auto domain data because this is specific to our domain data since this will be an attribute let's also append it with the attribute now inside here i'll have to inherit this from the auto data attribute which we used in our test earlier this allows us to override some of the auto fixture properties that can be used for our test now in this specific case i want an idea to be added whenever it is generating a brainstorm session class so let's create a new constructor and call in the base method now this base method accepts a function so let's create a func here and create and return a new fixture so let's say where fixture is equal to new fixture this fixture class is coming from auto fixture which is responsible for automatically generating all the objects that we pass in through the function parameters now this is automatically happening through the auto data attribute when we used it earlier since we want to modify some of these behaviors we are explicitly doing that inside this custom attribute so let's make sure to return this fixture to start with to add in this customization i just need to modify whenever the brainstorming session is created so let's go into this code and use the fixture dot customize and i can pass in the brainstorming session as a generic property so let's use brainstorming session so i'm customizing this whenever a brainstorming session is being created now this gives us a specific builder that we can use to build a brainstorming session so let's say c which is a customization and specify c dot do which is to do something anytime the object is created now inside this do method we will get again an action which the brainstorming object with us so let's call that as b to represent brainstorming and call the b dot add idea method and then all we need is an idea class which we can again resolve from the fixture itself so let's use fixture dot create and specify the object that we want in this case this is going to be idea now this can feel a bit tricky when you start with but since i am used with auto fixture and i have used this library long enough i know this is how to customize you can either copy and paste from here or always google and look for answers inside stack overflow or in the github repository of auto fixture itself now all that we are doing here is to customize the brainstorming session anytime it's created so we get a customization inside that we specifically call a do method which is to invoke this particular method and it adds an idea object to that to start using this attribute from the test let's go to the controller test and use this instead of the auto data so let's specify auto domain data which is now a similar attribute let's put a breakpoint here and again click debug we have the new idea populated as before let's navigate to the test session which now also has an ideas being populated so we have one item because inside the do method we called just once so we can see one idea which has random values again so if you look at these descriptions you can see these are random goods so the value for an end is also random and it has the name and the name with a good as expected now order fixture is automatically doing that for us as well so now if i continue execution of this test it succeeds as expected now i have completely removed the need of creating a custom brainstorming session using the get session method so any place that we are using this session method we can now replace it by simply using it inside the function as a parameter let's remove all this code so that all the test using this will start throwing an exception so let's now use brainstorming session from the function parameter so let's say test session remove this let's scroll up and fix the other test as well so here we have a get test session called directly so instead of this let's pass in a test session let's come here and call the brainstorming session and say this is the test session now since the test session id is used here we can remove this and instead of that we can use the test session dot id that's the value that we need in this particular example so let's remove that as well and update these tests so now instead of fact we need to make sure we use theory and also we use the appropriate auto domain data attribute so let's scroll up again now instead of this test session we can again use test session and pass in the brainstorming session through the function parameter so let's name this test session i can again delete this and instead of test session i can say test session dot id similarly fix that in here as well let's change this fact to theory and domain data attribute now all of this test is no longer using the get session method so let's make sure the build succeeds and run all the existing tests so let's right click and run the selected unit test all three of the tests that we modified are failing in this example so let's navigate to that to understand what is happening now here it's saying it's expected to be 2 but the actual is 1. this is because the new idea.session id and the test session dot session id are now two different ids so we'll have to make sure that we set them as the same so inside the new idea model so i can say this particular new idea dot session id is belonging to the test session dot id now this is something that we had done earlier by using the test session id as a parameter and making sure that it is being used by both the properties since this is the only property that i care for in this particular test i can explicitly set it inside the test arrange phase i also need to make sure that this is using the auto domain data attribute instead of the auto data attribute so let's run this test again to make sure this is fixed the next time the test runs that has successfully passed let's navigate to the next test that fails so in the test error here we can see this is being expected as one but it expects a random goet so it looks like there is some hard coding of the names still left so if we look at the test we can see this is a certain dot equal on the one which was a hard coded property if we want to keep this the same we can modify the test sessions the idea property so let's say test session dot ids so here we know that the first object will be populated and we can say the name is going to be 1 in this particular case so we can say equals and set this to be 1. so let's run this to make sure this is now succeeding as expected that text is also fixed so let's navigate to the last one which i think has a similar issue because it says expected one and the name is different so let's again copy and paste the same code or write this again here so let's come here and specify test session dot ideas and explicitly select the first item and set the name to be one let's come back to unit test select all these and run it again to make sure it's all successful all the tests are passing so let's go to our command line add on all the files and commit this so let's say added the auto domain data attribute similar way of injection can be updated in the other test as well so if we go to the home controller test let's expand this so let's go to folding and say expand all here we use the get sessions method which returns a list of brainstorming session so let's copy this let's make sure to delete these code so that we don't use this anymore so just delete all of that and instead of calling the get brainstorming sessions let's simply inject this in so inside the constructor we can say list of brainstorming sessions and say brainstorm sessions so instead of calling this method let's replace this with this particular property note here i am injecting a list of object in this particular case order fixture will handle that as well so instead of fact let's make this theory and also make sure to assign the auto domain data attribute that we created let's navigate to this test pass in that value and start using this instead of the method value so let's say brainstorming sessions let's update this to be theory and use the auto domain data attribute so let's come down and make sure to debug this again here we have the brainstorming sessions being injected in by auto fixture by default auto fixture chooses to populate three values inside a list there is a good post by mark siemann who is the author of auto fixture on why he has chosen this default but let's continue on with this test and execute this so this is successfully passed now if we run all the tests in this solution we can see one of these tests is breaking if we navigate to that we can see here this is asserting on two on the model count this is because earlier when the brainstorming sessions was created using the get sessions method it was automatically returning only two items but now since auto fixture is automatically returning 3 this is failing now i could go and change this to 3 and run all the tests to make this work so let's run this again to make sure it's working as expected but what if you only want two items and you don't want to modify this test as i just did so in this case you can go and update auto fixture to instruct that when you see a list just populate two items you could also create a custom attribute let's see how we can do that now i will not write up the whole attribute so i'll go to a stack overflow question which has this similarly solved so here somebody asks how can i create a custom collection size attribute now you can simply specify the collection size when you use order fixture so when you have a list of wind it says collection size of five and it just populates five items the next it says zero which means it will be an empty so let's use this collection size attribute in our class as well i will simply copy and paste all of this code into our source code so let's navigate inside here go to sample test create a new class so let's call this collection size attribute and paste the whole code so let's make sure to include all the missing references and build this so this builds perfectly fine so let's start using this collection size attribute navigating back to the home controller test here we expect two so instead of just specifying the list let's go and specify the collection size attribute as well so let's use this attribute and pass in the value of 2. now when auto fixture sees this it will just populate two items if you want to understand this code this creates a custom attribute which is for this collection size and it basically makes sure that from the fixture it creates only the specific number of count so this is using the create mini from the fixture and specifying the count inside this implementation if you want to understand this in detail i highly recommend checking that stack overflow link which i will put in the description below so let's navigate back to the home controller test make sure to debug this to see what's happening now we have the brainstorming sessions now this only has two items populated inside of that so this is because of the collection size attribute that we just specified if we continue the execution it will work just as expected so let's navigate back to the command line add in all these changes that we just did let's make sure what files we have so we have the collection size attribute and also the home controller test because we updated the list so let's commit this and specify added collections and collection size attribute let's navigate back close all this so let's just have the home controller and let's look at the example where we added the i logger inside the constructor of one of these implementations let's see how we can fix that so rather than using home controller and specifically creating an instance here we can use order fixture to inject this as well but if we go into the home controller class we can see here this uses an interface so when you use an interface along with auto fixture you need to instruct how to create this now in this particular example in the test we had used moq to create the mock object similarly we can instruct auto fixture to automatically use mock for us so let's go and add a new nuget package into this solution right click and say manage nuget packages inside here you can see there is an auto fixture dot auto mock library this automatically integrates moq library with auto fixture so let's install that and see how we can use this in our code i have this nuget package installed now if i come to this particular function let's start using the home controller from auto fixture so let's call this as controller let's remove this because we no longer require that now the home controller passes in the i brain repository through the constructor now by default auto fixture is set to use the default constructor in this case this home controller does not have one but if you look at the controller class it does have one so let's go and specify to autofixture to use the controller with the maximum number of attributes this can be done again with an inbuilt attribute which is called greedy so the greedy has an implementation to look at the maximum number of constructor arguments and use that for construction so in this case i will use this to make sure that the home controller is created by using this particular construction method now if we run this without any change let's say debug this fails even before hitting the debug point now if you look at the error message it says auto fixture was unable to create an instance from this i brainstorming session repository because we have an instructed auto fixture to use the auto mock library that we just installed so let's go to our auto domain data attribute and instruct here to use the auto mock library so let's use fixture dot customize and pass in a new auto mock customization this is coming from the autofixture.auto mock library that we just installed now inside our test wherever we are using the auto domain data attribute it's also going to use the auto mock customization which will use moq to generate interfaces now if i come back to the test and debug this we can see this in action the breakpoint is successfully hit which means the controller object is created successfully and it also has the i brainstorming repository injected into it but if we continue execution on this we can see we are creating a new mock object inside this line and we are setting the mock repository calls on that new object but this is not the same object that is being used inside the home controller because auto fixture does not know anything about this object that we are creating here so because of which if i continue execution this test is going to fail because the expected assert will not work as expected so if you look at the assertion you can see this expected too but it returned zero this is because the moq is failing now to fix this we need to make sure that the same instance of i brainstorming session repository is also used by the home controller to do that we can get this injected in by order fixture itself so let's specify the mr ck i brainstorming repository and say mock repo in here so now rather than creating it from the class we get this injected in but even in this scenario auto fixture by default creates a new instance anytime a type is requested for it so what happens is when it receives this particular line it creates a new instance and when the home controller request for another mock instance it creates a new instance of that as well but what we want both of them to be the same instance so if we navigate back we can use the frozen attribute which is very similar to the greedy or the collection size attribute just that it freezes that particular instance so now with the frozen attribute applied whenever we request for the mock of this repository it creates a new instance and freezes that just like a singleton instance in a dependency injection container now once that is frozen anytime another class or the similar type is asked for it uses the same instance so note the order in which you specify the frozen attribute and the next class is important because we first need to freeze that particular instance and then make sure the home controller also uses it appropriately now if you interchange this order the test will fail again i talk about this in my auto fixture series as well if it's confusing for you so let's run this again to make sure this is working as expected the test is passing so here we get a frozen mock which is being set up on this particular line and then we use the same mock inside the controller because auto fixture takes care of it for us so now if you look at this source code we have considerably reduced the lines of code that we need to write to arrange this test now it's just one line which is to set up the brainstorming sessions so similarly if i come down i can change this home controller so let's come here specify home controller and specify controller as the attribute we can delete this creation of the home controller now instead of creating a new mock of the repository i can use this from the function itself so let's specify frozen and pass in this mark of the repository so let's say mock repo and delete this line as well now let's make sure to use the greedy attribute so that it uses the constructor with the maximum parameters this sets it up and creates the model.add error and it creates the test as expected so this is explicitly stating this has an error on this session name property let's run this to make sure we have not broken anything this test also successfully passes similarly if we scroll down we can see one more test with this attributes so let's copy all of that let's make sure to use that inside here and let's also specify this is an auto data instead of fact now we can remove the mock repo that we are using inside of here because we get that injected let's also make sure to remove the controller creation now in this it's explicitly setting the new session model with a test name so we can very easily move this as well inside the function as auto fixture can create this for us so let's create new session let's make sure to specify the full type in this particular case and remove this code as well let's run this to make sure we haven't broken anything and the test is successful now all of our test is updated to use the home controller through order fixture and it is directly passed in through the function now if i go to this particular class and let's say as before we add in a new i logger implementation so let's say i logger of home controller let's call this as logger and make sure to add a backing property this new logger has nothing to do with the existing test because the existing test was completely testing a different behavior so let's build this application and it will still build as expected because none of the tests are depending on this particular construction and takes in the i logger now if i run all the tests so let's go back and run all the tests inside the solution and it still passes as expected because whenever an eye logger of home controller is requested auto fixture is going to use auto mock and automatically create this instance for us so we didn't have to make any change to any of our tests to get this to work so let's go to our console let's add all the files let's look at the files that we have added we have changed the home controller because we added the i logger interface we also added in some of the attributes and the auto mark library so let's commit this and say order fixture with moq let's close this and let's navigate back to our home controller test now here if you look at the arranged phase this is becoming very minimal setup so all these has just a few lines that is setting up some of the things that's absolutely required for the test in this particular phase you can see this is still using the new session but it's using the session name and making sure it is empty so since we are not passing in any value this is empty and it throws the exception of this model error now rather than hard coding this class name which is what this is doing in this particular test so if you go to the new session model it is looking at this session name so we could go and use the name of instead of hard coding it then we at least get this whenever a refactoring is happening so let's say home controller dot new session model dot session name so this automatically uses the name from this let's make sure we haven't broken anything by running this test again and it passes as expected so let's add that and commit it updated session name this test class now looks much cleaner because we have very minimal step and arrange phase and it is also robust to changes we saw when we changed the home controller nothing broke inside our test similarly if we go into the api ids controller test we can start cleaning this up as well or the same with the session controllers test so here this still has the get sessions method so let's remove this and start using this by using auto fixture so let's as before instead of this use the theory attribute and also make sure to specify the auto domain data attribute now since we need to pass in some values let's get in the session controller through here so let's say session controller pass in controller make sure to specify the greedy attribute so that it uses the constructor with the maximum parameters delete this line so in this case we don't have any arranged phase at all now if we scroll down let's update this get sessions so here instead of fact we can use theory and also specify auto domain data take a list of brainstorming session and name this brainstorming sessions so let's use this instead of the get sessions call now this expects the first or default so let's use that so this particular test expects a specific test session so we can go and modify one of the test sessions with this value of one so if we look at the brainstorming sessions we can set the id property to one of these values so let's say brainstorming sessions of xero dot id and set it to the test session id let's run this test to make sure we have not broken anything now this expects that name this expects to be test one but this is the hard coded name that's similar to us before we can go and update that first value to be test one so let's duplicate this and update the name to be the same as what is being expected so that is test one now this also tries to match on the day and make sure that it is two so in here if we want we can go and update the particular value for the date and update it to be with having a date of two so let's say date created and specify daytime offset dot parse and specify a day which has two inside it so let's specify july to 2021 let's run this again to make sure we have not broken anything this time the test passes as expected now i'm explicitly overriding some of the values that is of interest to me for this particular test now i'm not sure why this test is exactly written like this but since i didn't want to change that i have just modified it to fix it as i need but even in this case you can see majority of the work is done by auto fixture we didn't have to create the brainstorming sessions but just update a few properties inside that now if you want to pass these as parameters you can also use that by using the inline attributes let's navigate back to the console let's add all these changes it's only the session controller so let's say commit minus m updated the session controller test similarly like we did in the other test we can move the session controller and the mock setup to the function injection as well i'll leave that as an exercise for you to try out on this particular repository i will push this all the changes that i have made into a repository and put the link in the video below i hope this helps you to refactor some of the tests that use at work today the patterns that we have seen here are very common that i've seen in most of the applications that i have worked with so i'm sure you would be also using of some patterns similar now if you haven't used auto fixture before i highly recommend checking out that series in this youtube channel i'll have a link for that in the description below if you have any questions feel free to ask me in the comment below if you like this video please make sure to hit the like button to be notified of future such videos make sure to hit subscribe thank you and see you soon
Info
Channel: Rahul Nath
Views: 9,407
Rating: undefined out of 5
Keywords: unit test asp.net, unit test asp.net mvc, unit tests asp.net core, asp.net core unit testing, dotnet unit, dotnet unit testing, dotnet unit test controller, AutoFixture, test builder pattern, moq .net core, refactoring tests in .net, writing tests in .net core, maintainable tests in .net, xunit .net core web api, xunit .net core, how to unit test asp.net core application with constructor dependency injection, how to unit test asp.net core
Id: DbK1NVRQZvs
Channel Id: undefined
Length: 42min 18sec (2538 seconds)
Published: Fri Jul 30 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.