The Ultimate Guide to Testing in .NET

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
how do you test your.net application do you just mock the out of everything and write brittle unit tests or do you appropriately apply different aspects of the testing trophy the testing trophy huh what am I talking about so for context when I was a younger developer I used to just write unit tests and that would end up mocking everything and from my perspective I thought I was killing it I was writing textbook unit tests for I would just test little units of code because I had these mocks surrounding the code I was testing my code coverage was hi hooray and my code was super decoupled to allow all this mocking because in my head I thought any type of hard dependency was just pure evil but in reality as I would soon discover my tests were brittle and not helpful so whenever I wanted to refactor some code I would also have to make massive changes to the tests because the tests were so closely tied to the structure of my code so with that I didn't really want to refactor at all because it would take so much effort which in the end somewhat defeated the entire purpose of the tests which is the ability to regression test the code that has changed and of course there was other drawbacks of just writing unit tests because yeah I was verifying that these little units of code were working but I wasn't verifying that all of these units of code worked together I wasn't verifying that my application even started or performed as expected now if I had known about and understood the testing trophy I would have understood the implications of just writing unit tests I could have explored different testing approaches and I could have maximized the power of my tests so the testing trophy captures the main different types of tests as well as their implications or return on investment the trophy includes four different types of tests so let's go through each type of test understand the implications of the test and learn how to integrate the type of test into your.net application starting at the bottom of the testing trophy we have static testing so these catch type errors compile errors typos Etc and they're going to warn you before you even compile your code and sometimes they might block you from compiling your code altogether these are low effort they ever report in real time so we get instant feedback while we're typing and they're incredibly valuable during development because we don't have to compile our code or run our code in order to catch silly mistakes but obviously these tests can only get you so far of course they're not going to be able to test your business logic or run your code in Visual Studio we get this type of testing for free we'll get compile errors reported to us automatically and visual studio will also run static analysis in the background to warn us about any potential issues in our code moving up the testing trophy we have unit tests so unit tests verify that an isolated unit of code behaves as expected that said you might have to leverage a lot of mocking to ensure that you're isolating the unit under test unit tests are fast or at least they're supposed to be they're somewhat low effort depending on how much mocking you have to do they're really good for testing edge cases you can pass in a bunch of inputs and outputs and get quick results on your tests and they're great for code coverage if you care about vanity metrics on the other hand as I alluded to in my personal story unit tests can be brittle if they rely on too much marking and also unit tests don't give much feedback about how the application works as a whole overall I think unit tests are great for testing Core Business logic edge cases utility functions but not things like Getters and Setters of course or any kind of pass-throughs like a view model for example that just delegates to another service and doesn't have much logic nonetheless unit tests are still beneficial in some cases so let's Implement one in our solution the first thing we're going to do is create a new project there's plenty of different testing libraries out there but I prefer end unit so I'm going to create an N unit test project I'm going to name this test project the name of my application reservim DOT test uh Target the.net version that matches the application that I want to test and create now for this example I'm going to leverage a unit test for testing some Core Business logic so I want to ensure that this tostring method on my room ID value object returns a string that satisfies the requirements for a room ID string so in my test project I'm going to match the structure of the application I want to test so I'm going to add the new folder first for models because that's where the remod class lives and inside this folder I'm going to add a new class for the Vroom ID test and in order to test the rim ID class that lives in our reserving project we're gonna have to add a project reference from the test project to our application now in our remodtest class we can write our first test so we're going to create a function that represents our tests and what we want to test we want to test the tostring method on our vroom ID and we want to assert that it returns a unique room ID and since this function represents a test we're going to mark it with the test attribute as part of end unit and now following the philosophy of a range act and assert let's write our test so first we're going to arrange and this involves just instantiating the rim ID that we're going to test now we want to act so we're going to execute the method that we're testing and that's two string on the room ID and lastly we want to assert the most important part of testing we want to assert that the Vroom ID string is equal to what we expect depending on our vroom ID and now in visual studio if we come over to the test Explorer we can see our test in here and we can run it and our test passes and runs pretty quick moving on to my favorite part of the testing trophy we have integration tests A wise man once said write tests not too many mostly integration so integration tests verify that several units of code work together and behave as expected it involves very little mocking although external interactions such as file system database or API interactions should still be mocked integration tests are still pretty fast they're low effort to write in my opinion although there is some upfront medium effort in setting up reusable mocks for external interactions with little mocking and running several units of code together integration tests can give you lots of feedback regarding how your application is actually working and easily the greatest benefit of integration tests is you end up with less brittle tests which allows easy refactoring and regression overall I think integration tests are great for testing the integration points of your application so for example a view model in an mvvm application is going to integrate things like commands and services together so rather than writing a brittle unit test for the v-model why not leverage an integration test and make sure that the viewmodel is correctly integrating things like commands and services together all the way down to your API or database layer and get more feedback about how your application or your view model is behaving actually rather than talking about it let's integration test the viewmodel all the way down to the database layer similar to unit tests integration tests are run with the test Runner such as end unit so that being said it's perfectly fine to put integration tests in the same test project as you unit tests now for our integration tests we want to assert that the make reservation view model will create a reservation in our database when we submit so we're going to be testing the make reservation V model all the way through the make reservation command down through the hotel store to make a reservation through our actual hotel to make a reservation through our reservation book to add a reservation all the way down to our I reservation Creator which in our case saves the reservation to the database so this integration test is going to give us a lot of confidence that making reservations works so in our test project again matching the structure of our application we're going to create a new folder for view models and in this folder create a new class for the make reservation V model test similar to our unit test we're going to create a function that represents our test and we're going to mark it with the end unit test attribute so we want to test that executing the submit command with a valid reservation will create the reservation in our our database now since this is an integration test we want to make sure that the make reservation view model has all of the dependencies that we need and as I laid out there are quite a lot of dependencies so in my opinion I found the best way to manage this is with a dependency injection container in your test so we'll create a new service collection and simply register all of the required dependencies for the make reservation view model I would also recommend extracting this somewhere so that you can reuse it between tests or if possible importing the service collection that you use in your actual application for your integration tests but for this demo we're just going to define the service collection within our test one key thing to point out with this service collection is we are registering an in-memory DB context so this DB context is not going to be hitting an actual database file it's going to be working in memory so we're essentially mocking our external interaction to our database and this is key because it's going to make our test execute faster and we want have to worry about any setup or tear down for an actual database file or server between tests now we can build our service provider and for this test we're going to be integrating with our database so before we do anything we're going to have to run migrations against that in-memory database so that we have all the database tables spun up that we're going to interact with now we can resolve our make reservation V model from dependency injection and we can take that view model and fill out the required fields for submitting a new reservation then we can take our submit command and execute it which is going to funnel down all the way to our database and create our new reservation so that said we can take our in-memory DB context and try to find the reservation in our database that matches the reservation we just tried to create and then we can assert that the reservation was created and is not null and if we run this integration test it passes it's still kind of fast at least less than a second but most importantly we verified a critical part of our application is is behaving as expected now last but certainly not least at the top of the testing trophy we have functional or end-to-end testing these types of tests verify that your application starts up and runs successfully and they also verify that your application satisfies features from a user or client perspective that said we're literally going to run the application and interact with the application from the outside now I've made a distinction here between functional versus end-to-end tests and although these tests take the same approach of interacting with the application from the outside they are significantly different so functional tests involve testing your application in isolation and using mocks to interact with databases apis or anything outside of your application whereas end-to-end tests on the other hand involve hitting real databases real apis Etc and some sort of test environment while end-to-end test will give you a lot of feedback regarding how your system is performing as a whole it can be a lot of effort to maintain a test environment and it's certainly frustrating when testing your application or failing just be because some kind of API or database isn't working correctly in your test environment so functional testing and running your application against mocs can be very helpful in avoiding the issues with test environments or end-to-end testing altogether and functional tests will still give you a lot of feedback regarding how your application is behaving so the main benefits of functional or end-to-end testing as I've mentioned you get a lot of feedback regarding your application it's satisfying to see some kind of Bot interact and verify your application is working it makes refactoring easy because of course these tests are interacting with your app from the outside it's not tied to any kind of structure in your code so you can refactor all you want and regression tests but on the other hand these types of tests take a lot of effort to set up maintain right and they take a while to run in general it can take multiple seconds for your test to execute so that being said functional or end-to-end tests are best used for testing the core use cases of your application you wouldn't want to have a bunch of end-to-end tests that test every single little condition in your application because it would require a lot of Maintenance your test Suite would be slow and then your PRS would take forever to get merged now as I mentioned functional or end-to-end tests take significant effort to set up so I'm not going to be demonstrating these tests here but I have quite a few videos and even a live stream where I dig into functional and end-to-end testing topics so I'll make sure to link those and with that we have covered the testing trophy we've gone over static unit integration functional and end-to-end testing so next time you're writing a test think about the testing trophy are you choosing the right test for the scenario will this type of test have maximum return on investment is this a brutal test am I mocking too much these are just a few questions that might come up when you're attempting to test your application and really the best way to get good at answering these questions per scenario is with practice and experience so that being said review the testing trophy often keep it in mind make sure you understand it and ultimately maximize the return on investment from testing your application [Music] [Music]
Info
Channel: SingletonSean
Views: 1,630
Rating: undefined out of 5
Keywords: wpf, programming, visual, studio, xaml, custom, generic, system, display, c#, how, to, series, tutorial, easy, time, maintain, design, code, register, static, state, default, view, style, wrap, panel, stack, first, action, void, model, data, error, class, clean, simple, sub, file, host, rule, logic, domain, app, tile, maui, shell, type, safety, dependency, injection, mock, isolation, xamarin, asp, net, api, database, test, e2e, functional, unit, automated, mvvm, testing, integration, brittle, learn, regression, service, fast, lint, format, user, automation, ai, robot
Id: 8Tb61_EX3DM
Channel Id: undefined
Length: 13min 18sec (798 seconds)
Published: Wed Nov 01 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.