If Theow Up Once Will Do It Again? Glucose Test

Sometimes in that location are cases where we desire to throw a specific exception in our code. When yous are writing your tests, how do you account for this? In this commodity I will work through examples of how to unit exam C# code that's expected to throw exceptions.

Testing Series

I plan on making this article just one of many articles that are all to do with testing your C#/.NET code. This article is the 2d in the series. My previous article was an introduction to unit of measurement testing C#/.NET lawmaking with the assistance of the xUnit.Cyberspace testing library. Here is the C#/.NET testing series thus far.

  1. Unit Testing Your C# Code with xUnit
  2. Unit Testing Exceptions in C#

For this article, I volition outset with the code I wrote in my previous article. If you'd like to see that code, I've posted it on my Github, and y'all can see information technology here. If yous see something wrong or something that could be improved, feel free to submit a pull request! In that commodity, I wrote a SpeedConversionService whose sole purpose was to catechumen incoming speed units expressed as kilometers per hour into miles per 60 minutes. Using a examination driven development (TDD) Red-Green-Refactor arroyo with the assist of xUnit, I did non touch on the codebase without first writing a failing exam. For this article, I will proceed using a TDD arroyo.

The Code for this Article

If you would similar to see the total source, including all the code and the test project, I've posted the code specifically for testing exceptions on my GitHub. Every bit always, if you have a suggestion or feel y'all could make it ameliorate, feel gratuitous to submit a pull request!

Exam for Exceptions using xUnit's Assert.Throws<T>

xUnit kindly provides a nice way of capturing exceptions inside our tests with Affirm.Throws<T>. All nosotros need to do is supply Assert.Throws<T> with an exception blazon, and an Action that is supposed to throw an exception. Since we're following Red-Green-Refactor, nosotros're going to start with a failing examination. Nosotros're going to test the example where we call SpeedConversionService's ConvertToMilesPerHour method and pass it -1 equally the inputted kilometers per hr.

Since speed, in the math and physics world, is considered a scalar quantity with no representation of direction, a "negative" speed isn't possible. In our code, we need to add together a rule where we cannot convert negative values of kilometers per hr. We want to throw an exception, specifically an ArgumentOutOfRangeException, if the ConvertToMilesPerHour method is passed a negative input. Here'south how we'll do it with xUnit.

              [Fact] public void ConvertToMilesPerHour_InputNegative1_ThrowsArgumentOutOfRangeException() {     Assert.Throws<ArgumentOutOfRangeException>(() => speedConverter.ConvertToMilesPerHour(-i)); }                          

Start, we decorated the examination method with [Fact]. [Fact], as I mentioned in my previous commodity on unit testing C#/.Internet code with xUnit, is used to tell the examination runner to really run the test. If the exam runner completes the test without throwing an exception or failing an Assert, the examination passes.

Next, nosotros provide the blazon argument, which needs to be a blazon of Exception, the type of exception nosotros wait our lawmaking to throw, ArgumentOutOfRangeException.

Finally, we laissez passer in an Action every bit an empty lambda expression that simply calls our class nether test SpeedConversionService'south ConvertToMilesPerHour method with -1 equally the input parameter.

If nosotros run our exam, it fails. Since nosotros're post-obit TDD, we'll easily beginning with a failing exam since we don't have whatever such code that throws an ArgumentOutOfRangeException. Here's the output from my Visual Studio 2019 Test Explorer.

Visual Studio 2019 shows a failing test

Now, we need to write the lawmaking to make our examination laissez passer.

              public int ConvertToMilesPerHour(int kilometersPerHour) {     if (kilometersPerHour == -1)     {         throw new ArgumentOutOfRangeException($"{nameof(kilometersPerHour)} must be positive.");     }      return (int)Math.Round(kilometersPerHour * 0.62137); }                          

All I've washed is added a new guard clause that checks if kilometersPerHour is -1. If it is, it volition throw the exception. Our code should now pass the examination because we throw the expected ArgumentOutOfRangeException. I've besides used C#'south string interpolation and the nameof operator to specify the exception bulletin. The nameof operator will just enforce the name of kilometersPerHour is consistent with what we place in the exception message via compilation.

Visual Studio 2019 Test Explorer now shows all tests are passing

Great! Our test is at present passing, merely nosotros nevertheless have a problem. What if we input -2? Let's write a test.

              [Theory] [InlineData(-1)] [InlineData(-2)] public void ConvertToMilesPerHour_InputNegative_ThrowsArgumentOutOfRangeException(int input) {     Assert.Throws(() => speedConverter.ConvertToMilesPerHour(input)); }                          

I've changed our test to use the [Theory] and [InlineData] attributes instead of the [Fact] attribute. Equally I demonstrated in my previous article, this will allow usa to write less code to perform more tests. Now, let's run across what happens when we run all of the tests.

Visual Studio 2019 Test Explorer again shows a failing test

We need to modify the lawmaking to throw an ArgumentOutOfRangeException for all negative input.

              if (kilometersPerHour <= -1) {     throw new ArgumentOutOfRangeException($"{nameof(kilometersPerHour)} must be positive."); }                          

The tests are all passing once again in Visual Studio 2019 Test Explorer

Asserting Exception Messages

So far so proficient, our lawmaking now throws an ArgumentOutOfRangeException when inputting a negative integer, and our tests comprehend that. But what would we practice if nosotros added more requirements to our code, and information technology could throw ArgumentOutOfRangeExceptions for different reasons? For this, we tin actually ensure we've thrown the correct exception past inspecting the exception message of the return value of Assert.Throws<T>. A neat feature of Assert.Throws<T> is that it really returns the exception that was thrown within the passed Activeness.

Let's say nosotros desire our electric current ArgumentOutOfRangeException's to throw with the exception bulletin: "The input kilometersPerHour must be greater than or equal to zero." We'll need to alter our tests to account for this.

              [Theory] [InlineData(-ane)] [InlineData(-two)] public void ConvertToMilesPerHour_InputNegative_ThrowsArgumentOutOfRangeException(int input) {     var ex = Assert.Throws<ArgumentOutOfRangeException>(() => speedConverter.ConvertToMilesPerHour(input));      Affirm.Contains("must exist greater than or equal to zero.", ex.Message); }                          

I've changed the test method to store the event of Assert.Throws<T> into a variable, ex. Then I utilise Assert.Contains to ensure my ex, the ArgumentOutOfRangeException thrown past my code, contains the cord "must exist greater than or equal to nothing." I could have used Assert.Equals hither to ensure they exactly match, but I decided to use Affirm.Contains in example I wanted to change the starting time part of the exception message in the name of easier maintenance.

Our tests are now going to fail since the exception doesn't match what nosotros're expecting in the test.

Visual Studio 2019 Test Explorer shows our tests are failing

Now that we take our failing tests, let's write the code needed to make the tests pass. We'll demand to modify the exception message when we throw the ArgumentOutOfRangeException in our code.

              if (kilometersPerHour <= -one) {     throw new ArgumentOutOfRangeException($"{nameof(kilometersPerHour)} must be greater than or equal to naught."); }                          

And once again, our tests all pass!

All of the tests are passing within Visual Studio 2019 Text Explorer

Testing Exceptions Regardless of Test Framework

Okay, so testing for the exceptions our code throws is great and all, but what if we don't use xUnit in our test project? Nosotros can examination our exceptions using whatever testing framework such as MSTest, a still-popular testing framework developed past Microsoft, or NUnit, another wildly popular testing framework for .NET applications.

The way to do this is using good ole' fashioned C# try/take hold of blocks. Similar xUnit's way of testing exceptions with Assert.Throws<T>, it's unproblematic to test exceptions, but nosotros must exist mindful of the flow of the try/catch logic within our test methods.

If we wanted to ensure that our code simply throws the ArgumentOutOfRangeException given a negative input, we'd write our exam like this.

              [Theory] [InlineData(-1)] [InlineData(-2)] public void FrameworkAgnostic_ConvertToMilesPerHour_InputNegative_ThrowsArgumentOutOfRangeException(int input) {     endeavour     {         speedConverter.ConvertToMilesPerHour(input);     }     take hold of (ArgumentOutOfRangeException)     {         render;     }      throw new InvalidOperationException($"Expected {nameof(ArgumentOutOfRangeException)} but no exception was thrown."); }                          

While I used the [Theory] and [InlineData] attributes which are specific to xUnit, you lot could use attributes from whichever season of testing framework you choose such as [Test] or [TestMethod]. I've wrapped my call to ConvertToMilesPerHour inside a endeavour cake to give our examination method a chance to catch the exception within the catch block. If nosotros arrive at the catch block, which indicates our lawmaking threw the ArgumentOutOfRangeException as expected, we can simply return, as our work is done hither, and our test volition pass. Otherwise, if our code continues executing afterwards the telephone call to ConvertToMilesPerHour, we know our lawmaking didn't throw the ArgumentOutOfRangeException as expected, thus I throw an InvalidOperationException here with an appropriate bulletin to bespeak that something went incorrect, and the exam volition neglect.

Similarly, if nosotros wanted to check for a specific message after the exception is thrown, we demand to modify the grab block to audit the exception message.

              [Theory] [InlineData(-1)] [InlineData(-2)] public void FrameworkAgnostic_ConvertToMilesPerHour_InputNegative_ThrowsArgumentOutOfRangeException(int input) {     try     {         speedConverter.ConvertToMilesPerHour(input);     }     grab (ArgumentOutOfRangeException ex)     {         Affirm.Contains("must be greater than or equal to zero.", ex.Message);         return;     }      throw new InvalidOperationException($"Expected {nameof(ArgumentOutOfRangeException)} only no exception was thrown."); }                          

Our test must now satisfy an additional condition in that the exception message, ex.Bulletin, must comprise the string, "must be greater than or equal to zero." In one case once again I've used Assert.Contains, only any assertion appropriate for the situation in other frameworks will piece of work just as well. After we do the Assert.Contains, nosotros need to return from the method, otherwise the flow of execution will reach the bottom and throw the InvalidOperationException.

Wrapping Up

And there you have it! In this article nosotros've gone over how to unit exam our code that volition throw exceptions in a deterministic way. We can either use xUnit'south Assert.Throws<T>, which makes life while testing for exceptions pretty easy, or nosotros could practise the old fashioned test agnostic mode of using try/take hold of blocks. While xUnit does requite us some nice syntactic sugar for testing exceptions, we tin make the try/catch approach work equally well.

I've posted the lawmaking and testing projection on my GitHub if you'd like to check it out.

I hope y'all observe this commodity useful, and as e'er, happy coding!

Unit Exam Your C# Lawmaking Hands with xUnit and TDD prototype

Jan 12, 2020 by Republic of chad

Unit Examination Your C# Lawmaking Easily with xUnit and TDD

Unit of measurement testing your C# code has truly never been easier. Today I will innovate how to go up and running and unit of measurement testing your C# code in only a matter of seconds with one of the latest testing technologies, xUnit, using a Test Driven Evolution (TDD) arroyo.

Read Article

Multi-Tenanted Entity Framework Core Migration Deployment paradigm

April xi, 2021 by Chad

Multi-Tenanted Entity Framework Cadre Migration Deployment

There'due south many means to deploy pending Entity Framework Core (EF Core) migrations, especially for multi-tenanted scenarios. In this postal service, I'll demonstrate a strategy to efficiently utilize awaiting EF Core 5 migrations using a .NET 5 console app.

Read Article

Multi-Tenanted Entity Framework vi Migration Deployment image

April 10, 2021 by Chad

Multi-Tenanted Entity Framework 6 Migration Deployment

There's many ways to deploy pending Entity Framework 6 (EF6) migrations, especially for multi-tenanted product scenarios. In this post, I'll demonstrate a strategy to efficiently apply awaiting migrations using a .NET 5 console app.

Read Article

browncrianizied.blogspot.com

Source: https://chadgolden.com/blog/unit-testing-exceptions-in-c-sharp

0 Response to "If Theow Up Once Will Do It Again? Glucose Test"

Enviar um comentário

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel