Wednesday, April 24, 2019

Test-Driven Development in SQL Server

This blog post was originally published on the ThoroughTest website, back when that was a thing. As a co-founder and primary content contributor for ThoroughTest, I absolutely own the rights to this post and the source code to which it refers. I intend to reproduce each blog post here on my personal blog since the company is no longer in business.


We've heard from a few developers working with SQL Server that they're having a hard time justifying test-driven development of their "code" when a lot of their logic resides in stored procedures. That's a valid point: why use test-driven development (or write unit tests at all) if you can't cover the entire codebase? Well, that's a larger topic that we may discuss in a future post, but for now we can resolve the issue by introducing a method for unit testing SQL Server objects with the tSQLt testing framework.

For starters, you can check out the official documentation of tSQLt by visiting their website. We'll use the rest of this post to show a few simple ways we can do test-driven development using the framework. Keep in mind that this is a limited overview of what tSQLt provides and can do so just because you don't see a solution for your scenario here doesn't mean they don't have one. Review their official docs to get a more thorough understanding of what's possible.

For these examples we'll create a database called CookBook. You can create it on any instance of SQL Server (including Express) and any version since 2005. This database will be a repository for our recipes so we'll create two tables and one join table: Recipe, Ingredient, and RecipeIngredient. You can use the scripts below to follow along.

CREATE TABLE Recipe
  (
     Id          INT IDENTITY(1, 1),
     Name        VARCHAR(100) NOT NULL,
     DateCreated DATETIME2 DEFAULT GETDATE()
  )

ALTER TABLE Recipe
  ADD CONSTRAINT PK_Recipe_Id PRIMARY KEY CLUSTERED (Id)

CREATE TABLE Ingredient
  (
     Id          INT IDENTITY(1, 1),
     Name        VARCHAR(100) NOT NULL,
     DateCreated DATETIME2 DEFAULT GETDATE()
  )

ALTER TABLE Ingredient
  ADD CONSTRAINT PK_Ingredient_Id PRIMARY KEY CLUSTERED (Id)

CREATE TABLE RecipeIngredient
  (
     Id           INT IDENTITY(1, 1),
     RecipeId     INT NOT NULL,
     IngredientId INT NOT NULL,
     Amount       DECIMAL(4, 2) NOT NULL,
     Measurement  VARCHAR(100) NOT NULL
  )

ALTER TABLE RecipeIngredient
  ADD CONSTRAINT PK_RecipeIngredient_Id PRIMARY KEY CLUSTERED (Id)

ALTER TABLE RecipeIngredient
  ADD CONSTRAINT FK_RecipeIngredient_Ingredient FOREIGN KEY (IngredientId)
  REFERENCES Ingredient(Id)

ALTER TABLE RecipeIngredient
  ADD CONSTRAINT FK_RecipeIngredient_Recipe FOREIGN KEY (RecipeId)
  REFERENCESRecipe(Id) 
Now that we have our table structure we want to create a stored procedure that gets all the ingredients for a specific recipe in our cook book. We want to see the Ingredient Name, Amount, and Measurement for each item in the recipe and we want to specify the recipe by name. We know our requirements so now we can write our tests. Before we can start writing tests that will actually work we need to install the tSQLt framework, which is pretty simple to do. We just download the zip file, unzip it, and run SetClrEnabled.sql followed by tSQLt.class.sql on your database. Now that the framework is installed it's time to write a unit test.

The first thing we want to do is create a test class, which will be used to group our tests together. We prefer to create test classes with the name of the stored procedure followed by ".Tests" to be clear what's being tested and that it is a test class. Since a test class is just a schema we should see a new schema created after we take this action.

EXEC tsqlt.Newtestclass 'GetIngredientsByRecipeName.Tests' 
Now we have a test class for our stored procedure (which you'll notice we plan to name GetIngredientsByRecipeName) and we can create our first actual test. Tests in tSQLt are just stored procedures named a specific way so we can use our existing TSQL skills to create our tests. The first thing we need to do in our test stored procedure is setup our data, which we can do by having tSQLt create fake tables for the tables we'll need. Once we have our fake tables we can populate them with fake data. By using fake data we'll be sure that our tests will always pass without having to worry about what recipes are actually in the database. Here's what we have so far:

CREATE PROCEDURE
[GetIngredientsByRecipeName.Tests].[Test that all ingredients are returned]
AS
  BEGIN
      -- Arrange
      EXEC tsqlt.FakeTable
        'Recipe'

      EXEC tsqlt.FakeTable
        'Ingredient'

      EXEC tsqlt.FakeTable
        'RecipeIngredient'
  END 
The FakeTable procedure opens a transaction, renames the table being passed, then recreates a table with the same name and structure, but without any constraints, defaults, or triggers. After the code above runs, all three tables will be empty shells of their normal selves, allowing us to populate whatever data we want into them. We'll populate our fake tables with some fake data so we can anticipate the results of our stored procedure.

INSERT INTO Recipe(Id,Name) VALUES(1,'Grilled Cheese')

INSERT INTO Ingredient (Id, Name)
VALUES(1, 'Butter'), (2, 'Cheddar Cheese'), (3, 'White Bread')

INSERT INTO RecipeIngredient (RecipeId, IngredientId, Amount, Measurement)
VALUES(1, 1, 1, 'Tbsp'), (1, 2, 1, 'Slice'), (1, 3, 2, 'Slices')

INSERT INTO Recipe (Id, Name) VALUES(2, 'Quesadilla')

INSERT INTO Ingredient (Id, Name) VALUES(4, 'Tortilla')

INSERT INTO RecipeIngredient (RecipeId, IngredientId, Amount, Measurement)
VALUES(2, 4, 1, 'Tortilla'), (2, 2, .5, 'Cups')
Note: Even though we could normally exclude inserting values into the Id fields of Recipe and Ingredient (because they are identity fields and should automatically get the next number) we have to explicitly include them in our test because the fake tables are created without identity fields.

Now we have two recipes' worth of fake data and we know what we expect our stored procedure to do. We're going to want to compare the results of our stored procedure to what we expect so we'll create a temp table to store the results and a temp table containing our expected results.

CREATE TABLE #temp
  (
     IngredientName VARCHAR(100),
     Amount         DECIMAL (4, 2),
     Measurement    VARCHAR(100)
  )

CREATE TABLE #expected
  (
     IngredientName VARCHAR(100),
     Amount         DECIMAL (4, 2),
     Measurement    VARCHAR(100)
  )

INSERT INTO #expected
VALUES('Butter', 1, 'Tbsp'), ('Cheddar Cheese', 1, 'Slice'), ('White Bread', 2, 'Slices')

-- Act
INSERT INTO #temp
EXEC GetIngredientsByRecipeName 'Grilled Cheese' 
Finally, we'll actually compare the results of the two tables by executing the AssertEqualsTable procedure from the tSQLt framework. This procedure compares the contents of two tables for equality. Since we want to confirm multiple values across multiple rows, this option makes the most sense for us.

-- Assert
EXEC tsqlt.AssertEqualsTable '#temp', '#expected' 
Now we can create the stored procedure and run it using the Run procedure from tSQLt and passing either the test class or the test name to the procedure as a parameter. We'll use the test class name because going forward we'll want all of our tests to run whenever we make a change to our stored procedure. This is a good habit to get into now.

EXEC tsqlt.Run 'GetIngredientsByRecipeName.Tests' 
Good news; the test failed! There is no stored procedure named GetIngredientsByRecipeName yet so the test failed. We've established our first Red step in test-driven development! Create the procedure, but don't put anything in it yet.

CREATE PROCEDURE GetIngredientsByRecipeName
(
    @RecipeName VARCHAR(100)
)
AS
BEGIN
    PRINT 'Called'
END 
Run the test again and look at the output. This time, instead of getting an error message that it "could not find stored procedure 'GetIngredientsByRecipeName'" we see "(Failure) Unexpected/missing resultset rows!" and then a description of how the two tables failed to match. For more details on how to read this output, check out the tSQLt docs for AssertEqualsTable.

Let's finally modify our stored procedure to do what we want it to do: get the ingredients for the specified recipe.

CREATE PROCEDURE GetIngredientsByRecipeName
(
    @RecipeName VARCHAR(100)
)
AS
BEGIN
    SELECT
         Ingredient.Name
        ,RecipeIngredient.Amount
        ,RecipeIngredient.Measurement
    FROM Ingredient
    INNER JOIN RecipeIngredient
        ON Ingredient.Id = RecipeIngredient.IngredientId
    INNER JOIN Recipe
        ON RecipeIngredient.RecipeId = Recipe.Id
    WHERE  Recipe.Name = @RecipeName
END 
When we run our test one more time we see that it passed. Now we have our Green step so we'll review our stored procedure for any opportunities to improve. We don't see any so our Refactor step is complete without any changes.

We've got a new requirement that ingredient amounts should be summed up when the same ingredient is in the same recipe with the same measurement more than once. First we'll write the test:

CREATE PROCEDURE
  [GetIngredientsByRecipeName.Tests].
   [Test that ingredient amounts are summed]
AS
BEGIN
    -- Arrange
    EXEC tsqlt.FakeTable 'Recipe'

    EXEC tsqlt.FakeTable 'Ingredient'

    EXEC tsqlt.FakeTable'RecipeIngredient'

    INSERT INTO Recipe (Id, Name) VALUES(1, 'Salt Soup')

    INSERT INTO Ingredient (id, Name)
      VALUES (1, 'Salt'),
        (2, 'Chicken Broth'), (3, 'Carrots'), (4, 'Leather Boot')

    INSERT INTO RecipeIngredient(
      RecipeId,
      IngredientId,
      Amount,
      Measurement
    )
      VALUES (1, 1, 1, 'Tbsp'), (1, 2, 10, 'Cups'),
        (1, 3, 10, 'Carrots'), (1, 4, 1, 'Boot'), (1, 1, 16, 'Tbsp')

    CREATE TABLE #temp
      (
         IngredientName VARCHAR(100),
         Amount         DECIMAL (4, 2),
         Measurement    VARCHAR(100)
      )

    CREATE TABLE #expected
      (
         IngredientName VARCHAR(100),
         Amount         DECIMAL (4, 2),
         Measurement    VARCHAR(100)
      )

    INSERT INTO #expected
      VALUES ('Salt', 17, 'Tbsp'), ('Chicken Broth', 10, 'Cups'),
        ('Carrots', 10, 'Carrots'), ('Leather Boot', 1, 'Boot')

    -- Act
    INSERT INTO #temp
    EXEC GetIngredientsByRecipeName 'Salt Soup'

    -- Assert
    EXEC tsqlt.AssertEqualsTable '#temp', '#expected'
END 
Then we'll run all of the tests in the test class:

EXEC tsqlt.Run 'GetIngredientsByRecipeName.Tests' 
We get an exception: "(Failure) Unexpected/missing resultset rows!". We update the stored procedure:

ALTER PROCEDURE GetIngredientsByRecipeName
(
    @RecipeName VARCHAR(100)
)
AS
BEGIN
    SELECT
         Ingredient.Name
        ,SUM(RecipeIngredient.Amount)
        ,RecipeIngredient.Measurement
    FROM Ingredient
    INNER JOIN RecipeIngredient
        ON Ingredient.Id = RecipeIngredient.IngredientId
    INNER JOIN Recipe
        ON RecipeIngredient.RecipeId = Recipe.Id
    WHERE  Recipe.Name = @RecipeName
    GROUP BY
       Ingredient.Name
      ,RecipeIngredient.Measurement
END 
And finally we run all of our tests again:

EXEC tsqlt.Run 'GetIngredientsByRecipeName.Tests' 
This time our test summary shows that we have two tests that ran and both of them passed.

Stored procedures are an important part of database programming and sometimes play a large role in applications and architecture. Using the tSQLt framework we can realize the advantages of test-driven development even when we're working with SQL Server.

Tuesday, April 23, 2019

Letting Microsoft do the Wrapping with Fakes and Stubs

This blog post was originally published on the ThoroughTest website, back when that was a thing. As a co-founder and primary content contributor for ThoroughTest, I absolutely own the rights to this post and the source code to which it refers. I intend to reproduce each blog post here on my personal blog since the company is no longer in business.


We previously talked about creating our own wrappers for dependencies that do not have mockable interfaces. Specifically we showed how to wrap Microsoft's Random class in a wrapper so we could mock the return and confirm that we were making the calls. There's a slightly different way we can do this, using something Microsoft has included for a few years, called Fakes (and Stubs, too).

Note: Unfortunately, Fakes don't seem to be available for .Net Core just yet so we'll have to cross our fingers and hope they add that support soon.

Using Fakes and Stubs is actually kind of the same process as writing our own wrappers, except we don't have to write our own wrappers. Since we've already talked about why we'd wrap Random, we won't go into it again here. Instead we'll jump right into the "hows" of getting things up and running.

The first thing we need to do is create a fake for whatever namespace the class we're going to fake or stub is in. In this case, Random is in System so we need to create a fake of that assembly. To do that, we expand References in our test project, right-click on System and choose "Add Fakes Assembly" from the context menu. After a moment, there will be a new folder in the project called Fakes with two files in it: mscorlib.fakes and System.fakes. After another moment you will see references to those new files in the References for the project: mscorlib.4.0.0.0.Fakes and System.4.0.0.0.Fakes (the version numbers may be different, depending on what's out there when you read this). You should also see a new reference to Microsoft.QualityTools.Testing.Fakes. Here's a picture of what you might see:

Now that we've added the right references we'll get started with writing our tests themselves. First we have to create a ShimsContext to run our tests in. ShimsContext implements IDisposable so we can do this by utilizing a using statement:

   1:  // create the ShimsContext in order to use Fakes later
   2:  using (ShimsContext.Create())
   3:  {
   4:  }
Within the ShimsContext we can use Fakes to specify the exact data we want to receive when we use static methods. The first method here specifies that when DateTime.Now is called by the code under test, it should be detoured to use “09/12/2017” (we want our shuffler to shuffle two decks on Tuesdays so we always want this specific test to behave as though it is running on a Tuesday):

System.Fakes.ShimDateTime.NowGet = () => new DateTime(2017, 09, 12);
That's all we need to do in order for this test to work. When DateTime.Now is called by our Code Under Test, the call will get intercepted and re-routed to use 09/12/2017 instead of today's actual date. This way we've guaranteed that the day will always appear to be a Tuesday when this test is run. Here's the full test:

   1:  [TestMethod]
   2:  public void ShuffleShouldShuffleTwoDecksOnTuesdays()
   3:  {
   4:      // create the ShimsContext in order to use Shims later
   5:      using (ShimsContext.Create())
   6:      {
   7:          // arrange
   8:          // intercept the call to System.DateTime.Now and always return a date
   9:          // that we're sure falls on a Tuesday (09/12/2017 is a Tuesday)
  10:          System.Fakes.ShimDateTime.NowGet = () => new DateTime(2017, 09, 12);
  11:          var shuffler = new Shuffler();
  12:   
  13:          // act
  14:          var cards = shuffler.Shuffle();
  15:   
  16:          // assert
  17:          Assert.AreEqual(104, cards.Count);
  18:      }
  19:  }
Stubs are a little bit easier to work with and don't require the ShimsContext in order to use them. We can create a stub pretty easily by specifying which methods we want to stub for the stubbed object. Perhaps an example would be best here.

   1:  var randomStub = new System.Fakes.StubRandom
   2:  {
   3:      NextInt32Int32 = (minValue, maxValue) =>
   4:      {
   5:          if (position == 1)
   6:          {
   7:              position = 53;
   8:          }
   9:          position--;
  10:          return position;
  11:      }
  12:  };
Once we've created the stub we need a way to provide it to the Code Under Test, which brings us all the way back around to dependency injection. We can either provide the dependency in the constructor or we can create a public setter to do so. In these tests we're using Setting Injection to show how it would be done since our ThoroughTest guide focuses more on Constructor Injection. Here's the test in full to get a better idea of what's happening:

   1:  [TestMethod]
   2:  public void ShuffleShouldShuffleDeck()
   3:  {
   4:      // arrange
   5:      var position = 53;
   6:      // setup the Random stub so that when Next is called with two
   7:      // integers (min value and max value) we always return a number
   8:      // we know
   9:   
  10:      // what we're going to do here is go backward through the unshuffled
  11:      // deck so the "shuffled" deck that we end up with will just be an
  12:      // inversion of the unshuffled deck (KS will be first and AH will be last)
  13:      var randomStub = new System.Fakes.StubRandom
  14:      {
  15:          NextInt32Int32 = (minValue, maxValue) =>
  16:          {
  17:              if (position == 1)
  18:              {
  19:                  position = 53;
  20:              }
  21:              position--;
  22:              return position;
  23:          }
  24:      };
  25:   
  26:      var unshuffledDeck = new List<string>
  27:      {
  28:          "AH", "2H", "3H", "4H", "5H", "6H", "7H", "8H", "9H", "10H",
  29:          "JH", "QH", "KH", "AD", "2D", "3D", "4D", "5D", "6D", "7D",
  30:          "8D", "9D", "10D", "JD", "QD", "KD", "AC", "2C", "3C", "4C",
  31:          "5C", "6C", "7C", "8C", "9C", "10C", "JC", "QC", "KC", "AS",
  32:          "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S", "10S", "JS",
  33:          "QS", "KS"
  34:      };
  35:   
  36:      var shuffler = new Shuffler { Random = randomStub };
  37:   
  38:      // act
  39:      var cards = shuffler.Shuffle();
  40:   
  41:      // assert
  42:      var j = 51;
  43:      for (var i = 0; i < 51; i++)
  44:      {
  45:          Assert.AreEqual(unshuffledDeck[i], cards[j]);
  46:          j--;
  47:      }
  48:  }
You can see that we're creating an instance of the Shuffler class and then we're setting the Random property in that instance to the stub we created previously. It's important to note that we did not have to create a new ShimsContext in order for this to work properly. Fakes require the ShimsContext, but Stubs do not.

There's a lot we can do with Fakes and Stubs from Microsoft, but probably the best part is that this all comes out of the box with Visual Studio so we don't need to write our own wrappers or anything.

Monday, April 22, 2019

Changing your mindset for starting TDD

This blog post was originally published on the ThoroughTest website, back when that was a thing. As a co-founder and primary content contributor for ThoroughTest, I absolutely own the rights to this post and the source code to which it refers. I intend to reproduce each blog post here on my personal blog since the company is no longer in business.

Changing the patterns and practices of developers can be a lot like herding cats, especially if they have been following a personal standard for any length of time. It can seem that the harder you try to move people in one direction forcibly, the more resistance you will face. Not only will this resistance affect morale among a team, it will also create, hopefully, figurative claw marks and scratches all over the herder. The key to adoption for any new methodology is to show the overall benefits and have a transition plan. Changing an engrained mindset takes some time, but the results can be monumental and lead to a more productive and effective development team.

Test Driven Development (TDD) is a mindset. What exactly is a mindset? Well, a mindset is a set of beliefs, assumptions, and a perspective a person has about a topic. And, how exactly is TDD a mindset then? TDD is the perspective that it’s more important to understand a problem or requirement before finding or building a solution. This is characterized by writing unit tests before writing any code to satisfy those requirements.

Most developers have the belief that it’s easier to work on the solution first and then while doing so they will begin to understand the complexities of the problem. Is this belief wrong? No, but it’s generally not the most effective. One of the major goals of TDD is to become more effective in writing code and in that effectiveness quality will increase and bugs will decrease. This reason alone is why changing to a TDD mindset will be one of the more beneficial changes a developer can make in their career.

How many times have you or another developer written code weeks, months, or even years ago that maybe was not “clean” or that you even remember ever writing? That code has now become core to the application inadvertently. Today a new developer, or even yourself, makes a change to that code to solve a different requirement. The new code solves the new problem, but now an angry user calls the support desk and says that the feature they relied on for months has stopped working.

The cycle continues of writing code to solve a new problem, break an old feature, fix the old feature, and on and on it goes. This very concern is the solution a TDD mindset will solve. It solves the issue by the codebase always knowing what the desired outcome is for any line of code written because the developer had a clear understanding of the problem before ever writing functional code. Knowing the outcome and having a test written for it helps stop the perpetual cycle of “new code breaks old code” headlines that fill up release notes.

So, the question you’ll be having now is, how do you change to a TDD mindset? It’s all fairly straightforward and the first step is that when reading any requirement or learning of any new features or functionality needed is to ask one simple question: how do I test this? Another way to phrase it is: how do I know that the code I will write is going to satisfy the requirement accurately and completely? Write this question down on a sticky note and put it on however many monitors you have: “HOW DO I TEST THIS?” It cannot be stressed enough how important this question is when changing to a TDD mindset.

The next step for a TDD mindset shift is repetition. Repetition is key here. Asking yourself the above question over and over will help engrain the notion in your mind that understanding the outcome and impact of any requirement is way more important than finding a solution first. You wouldn’t casually build a house upon dirt and then later pour concrete under it, you pour the concrete first and then build the structure from blueprints. The idea is the same in TDD. Have a solid foundation of what needs to be accomplished before ever writing code.

The final step of changing your mindset to a TDD one is probably the most important. This is the step of implementation. It doesn’t do much good to only think about implementing the principles of a TDD mindset without putting them to actual use. It takes real practice to be able to implement anything new and TDD is no different. Without constant practice of getting a requirement, completely understanding it, writing unit tests, and then writing code, it will be very difficult to truly grasp the concept.

Adoption of TDD can be hard to overcome, but by just first thinking about how something can be tested before ever writing code you will have already taken the first step. At the very least start with that question in mind and slowly work your way towards the other steps in TDD. Through time and repetition, you will be well on your way to developing a new mindset that will result in more efficient code with fewer bugs.

Sunday, April 21, 2019

Using Wrappers for Non-Fakeable Dependencies

This blog post was originally published on the ThoroughTest website, back when that was a thing. As a co-founder and primary content contributor for ThoroughTest, I absolutely own the rights to this post and the source code to which it refers. I intend to reproduce each blog post here on my personal blog since the company is no longer in business.



At the end of that post we mentioned there is a better way to test the randomness of the shuffler and we'd discuss it in a future post. Well, here's the future post where we'll discuss it.

The randomization of our shuffler is based on the use of the Random class provided by .NET. Since the Random class doesn't have an interface we can't create a fake object that represents it. That means the Random class is a non-fakeable dependency of our Shuffler class. In this particular case it isn't really a problem to just allow the Random class itself to be called because there are no side effects of such a call. Imagine if we were trying to test a method that writes a file to the operating system, though. We definitely wouldn't want to let that call happen every time our test ran because even in the best case scenario it means we have to add clean up to delete the file when the test is finished. If you consider that tests can run in parallel and test accounts on build servers often don't have I/O permissions you can easily see how it wouldn't be a good idea at all to allow new files to be created during testing.

So what do we do about it? We definitely need a way to create fake objects to use in place of these real non-fakeable objects, but how? That's where wrappers can come into play. We can create a wrapper around the non-fakeable code, inject our wrapper, and use the injected wrapper instead of the underlying code. In the earlier blog post on proof of concepts we said that one of the steps was to identify inherently non-testable code. This is why. If we know about these types of limitations before we start writing our code (and our tests) we can account for them before we do anything else so we don't have to come back and do it later.

OK, we're using Moq to create our fake, injectable Random wrapper (remember that the term "fake objects" here can refer to mocks, stubs, fakes, spies, and dummy objects). In our test we're going to want to know how many times the Random wrapper was called so we're going to want a mock object. We're not going to dive into dependency injection options right now, but we are going to inject our wrapper as a dependency.

Since we're doing test-driven development we'd add the Moq NuGet package first so we can start writing our tests. Since we're only using Moq for testing we only need to add it to the CardGames.Shuffler.Logic.Tests project.

Right now we have a unit test that checks whether the cards are shuffled by iterating through the new deck of cards and checking whether the card in each position is different than the value of the card in the same position of the original (unshuffled) deck. We also check whether the value of the card is different than the value of the card one position before and one position after the same position in the original deck. That's useful, but we had to build in a tolerance to account for the possibility that the card some cards could have ended up in the same position after shuffling that they were in before shuffling. Since shuffling is random, this is a real (albeit slim) possibility.

What we want to do is write a unit test that can check to see how many times the Random class was called. We know from our proof of concept that we should call the Next method of the Random class at least 52 times to shuffle the deck. We also know that when we call the Next method we should pass in 1 and 53 as the parameters every time. We'll call the unit test ShuffleShouldGetAtLeast52RandomNumbersBetween1And53 and all we'll do is check whether we call the Next method at least 52 times.
   1:  [TestMethod]
   2:  public void ShuffleShouldGetAtLeast52RandomNumbersBetween1And53()
   3:  {
   4:      // arrange
   5:      var randomResult = 0;
   6:      var moqRandomWrapper = new Mock<IWrapRandom>();
   7:      moqRandomWrapper.Setup(p => p.Next(It.IsAny<int>(), It.IsAny<int>()))
   8:          .Callback<int, int>((minValue, maxValue) => {
   9:              randomResult++;
  10:          }).Returns(() => randomResult);
  11:      var shuffler = new Shuffler(moqRandomWrapper.Object);
  12:   
  13:      // act
  14:      shuffler.Shuffle();
  15:   
  16:      // assert
  17:      moqRandomWrapper.Verify(p => p.Next(1, 53), Times.AtLeast(52));
  18:  }

We're using Moq to create a mock implementation of a new interface called IWrapRandom. We're then configuring Moq to spy on any calls to the Next method of our interface (we're not spying on the actual Next method of the Random class). The assertion in our test is simply to check whether we generated at least 52 random numbers. The problem at this point, of course, is that we don't actually have
an IWrapRandom interface so the code won't even compile. Let's fix that.
   1:  public interface IWrapRandom
   2:  {
   3:      void Create();
   4:   
   5:      int Next(int minValue, int maxValue);
   6:  }

Our interface is really simple because we don't need very much right now. All we need to be able to do in our test is check whether we've called the Next method at least 52 times. In order to do that we need to be able to create an instance of the Random class (void Create()) and we need to have a Next method. Now we need to modify the Shuffler class to accept an implementation of IWrapRandom in its constructor and then we'll create a private, read-only field to hold the injected implementation of IWrapRandom.
   1:  private readonly IWrapRandom _randomWrapper;
   2:   
   3:  private Shuffler(IWrapRandom randomwWrapper)
   4:  {
   5:      _randomWrapper = randomwWrapper;
   6:  }

Now that our Shuffler has an implementation of IWrapRandom we need to change our code to use it instead of the actual Random class.
   1:  public Deck Shuffle()
   2:  {
   3:      var deck = new Deck
   4:      {
   5:          Cards = new List<string>(),
   6:          IsShuffled = false
   7:      };
   8:   
   9:      while (deck.Cards.Count < 52)
  10:      {
  11:          var position = _randomWrapper.Next(1, 53);
  12:   
  13:          if (!deck.Cards.Contains(_unshuffledDeck[position]))
  14:          {
  15:              deck.Cards.Add(_unshuffledDeck[position]);
  16:          }
  17:      }
  18:   
  19:      return deck;
  20:  }

Now we're using the injected implementation of IWrapRandom in our actual code and our new test should pass. Unfortunately, when we added the constructor that accepts IWrapRandom we broke our other two tests. For the moment, go ahead and comment those tests out so we can forge ahead and make sure our latest test passes.

Once we prove that our latest test actually does pass, we need to refactor our two existing tests so they compile, then make sure that all three tests pass together. Remember that unless we change functionality intentionally, our entire test suite should always pass. Here's what our test class looks like after we refactor it.
   1:  private Mock<IWrapRandom> _moqRandomWrapper;
   2:   
   3:  [TestInitialize]
   4:  public void Setup()
   5:  {
   6:      _moqRandomWrapper = new Mock<IWrapRandom>();
   7:   
   8:      var random = new Random();
   9:      _moqRandomWrapper.Setup(p => p.Next(It.IsAny<int>(), It.IsAny<int>()))
  10:          .Returns(() => random.Next(1, 53));
  11:  }

We added a new method called Setup that will run before each test in this test class. This allows us to reconfigure the mock of IWrapRandom before each test executes. We're setting up our mock object to use the actual Random class to generate and return random numbers. We have to do this so that our tests pass. If we don't configure the mock object to return a number then our code will fail when it tries to get the card from the unshuffled deck.
   1:  [TestMethod]
   2:  public void ShuffleShouldMoveAces()
   3:  {
   4:      // arrange
   5:      var shuffler = new Shuffler(_moqRandomWrapper.Object);
   6:   
   7:      // act
   8:      var deck = shuffler.Shuffle();
   9:   
  10:      // assert 
  11:      Assert.AreNotEqual("AH", deck.Cards[0]);
  12:      Assert.AreNotEqual("AD", deck.Cards[13]);
  13:      Assert.AreNotEqual("AC", deck.Cards[26]);
  14:      Assert.AreNotEqual("AS", deck.Cards[39]);
  15:  }

   1:  [TestMethod]
   2:  public void ShuffleShouldRandomizeADeckOfCards()
   3:  {
   4:      // arrange
   5:      var unshuffledDeck = new List<string>
   6:      {
   7:          "AH", "2H", "3H", "4H", "5H", "6H", "7H", "8H", "9H", "10H",
   8:          "JH", "QH", "KH", "AD", "2D", "3D", "4D", "5D", "6D", "7D",
   9:          "8D", "9D", "10D", "JD", "QD", "KD", "AC", "2C", "3C", "4C",
  10:          "5C", "6C", "7C", "8C", "9C", "10C", "JC", "QC", "KC", "AS",
  11:          "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S", "10S", "JS",
  12:          "QS", "KS"
  13:      };
  14:      var shuffler = new Shuffler(_moqRandomWrapper.Object);
  15:   
  16:      // act
  17:      var deck = shuffler.Shuffle();
  18:   
  19:      // assert
  20:      var numberOfMatches = 0;
  21:      for (var i = 0; i < 52; i++)
  22:      {
  23:          if (unshuffledDeck[i] == deck.Cards[i] ||
  24:              (i > 0 && deck.Cards[i - 1] == unshuffledDeck[i]) ||
  25:              (i < 51 && deck.Cards[i + 1] == unshuffledDeck[i]))
  26:          {
  27:              numberOfMatches++;
  28:          }
  29:      }
  30:      Assert.IsTrue(numberOfMatches < 5,
  31:          $"{numberOfMatches} is not less than 5");
  32:  }

We need to modify the existing tests to inject the mock implementation of IWrapRandom in our constructor.
   1:  [TestMethod]
   2:  public void ShuffleShouldGetAtLeast52RandomNumbersBetween1And53()
   3:  {
   4:      // arrange
   5:      var shuffler = new Shuffler(_moqRandomWrapper.Object);
   6:   
   7:      // act
   8:      shuffler.Shuffle();
   9:   
  10:      // assert
  11:      _moqRandomWrapper.Verify(p => p.Next(1, 53), Times.AtLeast(52));
  12:  }

Finally, we refactor our new test to stop creating a new mock of IWrapRandom and just go ahead and inject the one we're creating in the Setup method (which, remember, is already configured so we don't have to do it again here).

At this point our tests are successful, but if we were to actually run our code we'd have issues. That's because we haven't written an actual implementation of the IWrapRandom interface. We need to specify what should happen during a normal execution of our program. This is an important part of creating wrappers: our wrappers should wrap the smallest amount of code possible. Our real implementation of IWrapRandom looks like this.
   1:  public class RandomWrapper : IWrapRandom
   2:  {
   3:      private Random _random;
   4:   
   5:      public void Create()
   6:      {
   7:          _random = new Random();
   8:      }
   9:   
  10:      public int Next(int minValue, int maxValue)
  11:      {
  12:          return _random.Next(minValue, maxValue);
  13:      }
  14:  }

We don't want to put any logic in our methods because we can't test whatever logic we do put in there. Since the whole point of writing the wrapper in the first place was to be able to test whether and how many times the Next method was called, it wouldn't make sense to then put non-testable code in the implementation of the wrapper. Again, this is a really important part of wrappers. Try to keep your wrapper method focused on wrapping a single method of a non-fakeable dependency (the Next method of our wrapper only wraps the Next method of the built-in Random class).

Ideally, all code would be fakeable, but we don't code in an ideal world so sometimes we need to make small changes like this so we can verify our code works the way it's supposed to at all times.

Saturday, April 20, 2019

Test-Driven Development on Proof of Concepts

This blog post was originally published on the ThoroughTest website, back when that was a thing. As a co-founder and primary content contributor for ThoroughTest, I absolutely own the rights to this post and the source code to which it refers. I intend to reproduce each blog post here on my personal blog since the company is no longer in business.


Every developer knows there are times when you just have to play around with some code to see what works and what doesn't. Proof of concept code can be a valuable tool when you're learning something new, trying to figure out a new library, or a plethora of other reasons. Once you've written your proof of concept and it's time to turn into real, quality-driven code, how do you make the transition? This comes up a lot for us so we'll walk you through a few steps that will make sure your proof of concept can seamlessly transition to a test-driven application.

The first thing you'll want to do is take your proof of concept and really look at what it's doing. Think of it like a car: you know it runs, but now you need to really inspect how it runs. You need to look at each individual piece and figure out how they function.

Once you know how the concept code works you'll want to identify any areas that aren't inherently unit-testable. Let's say your proof of concept uses a packaged set of assemblies from a vendor that weren't written to be mocked, spied, etc. You'll want to identify those pieces before you try to start unit testing or it might be bad news later.

Next you'll want to generate some really loose technical requirements. We know, you thought technical requirements were a thing of the past (waterfall, anyone?), but they are sometimes still useful. This is one of those situations. Don't get too specific with them and don't spend a lot of time writing them. Just jot down what's happening in your proof of concept code now so you'll know what tests to write in a few minutes.

At this point you have a working proof of concept, a thorough understanding of how it's working, an awareness of which parts aren't unit-testable, and some really rough technical requirements. You're ready to start your real code now. From this point on you basically get to approach your test-driven process the same way you would if you had not created a proof of concept first. You'll write your tests based on your requirements, write just enough code so the tests can pass, then refactor the code (and the tests) until it all makes you happy. How about an example?

Our feature is a full-fledged card game suite. We ultimately want to have multiple games available where the user can choose which game to play, how much he wants to wager (just for fun!), how many decks of cards to use, and a few other options. The first step is figuring out how to effectively shuffle a deck of cards. No matter what we decide to do with any of the card games, if we can't shuffle the cards we won't create a positive experience for our users. For this sprint (we're agile), one of the stories our team has taken on is developing the card shuffling mechanism that will be used by all of the card games in the future. We decided to write a proof of concept to make sure we have a really solid idea of how we're going to do this (and whether it's even possible) before we start writing our tests and our code.

Now, we want to specify right up front that this isn't necessarily the best way to do this. We're showing how to do it because we know that we don't always get to do things the best way. In those cases we have to accept what we've been given and make the best of it, which is what we're about to do.

Here's what our proof of concept looks like right now:
   1:  public void Shuffle()
   2:  {
   3:      var deck = new Deck { Cards = new List<string>(), IsShuffled = false };
   4:  
   5:      while (deck.Cards.Count < 52)
   6:      {
   7:          var random = new Random();
   8:          var position = random.Next(1, 53);
   9:  
   10:         if (!deck.Cards.Contains(_deck[position]))
   11:         {
   12:             deck.Cards.Add(_deck[position]);
   13:         }
   14:     }
   15: 
   16:     deck.Cards.ForEach(Console.WriteLine);
   17: }

Now we want to go through our process so we can use test-driven development to build the releaseable, reusable shuffle code.
  1. Figure out how everything works
    This is a pretty easy one since our proof of concept code is so simple and small
  2. Identify areas that aren't inherently unit-testable
    We're using the System.Random class, which doesn't have an interface that we can mock so we'll have to do something about that.
    We're not going to cover how to mock this class in this post, but we'll get into it in the future
  3. Generate loose technical requirements
    1. Create an empty deck of cards
    2. Repeat steps 3 and 4 until the new deck is populated with 52 cards
    3. Generate a random number
    4. Put the card represented by the random number into the new deck if it isn't already in there
So now we know what's happening in our proof of concept and we can identify what tests we should write, at least for this part of our shuffler. We generated those technical requirements just so we'd really know what our proof of concept is doing, and therefore what our actual code should do. We don't necessarily need to write a separate unit test for each requirement we generated. In fact, we generally shouldn't write one test per acceptance criterion or requirement.

In this case we can probably get away with writing a unit test called ShuffleShouldRandomizeADeckOfCards. This test will check that after we call the Shuffle method we have a deck of cards that is not in consecutive order. Easy enough.
   1:  [TestMethod]
   2:  public void ShuffleShouldRandomizeADeckOfCards()
   3:  {
   4:      // arrange
   5:      var shuffler = new Shuffler();
   6:   
   7:      // act
   8:      var deck = shuffler.Shuffle();
   9:   
  10:      // assert 
  11:      Assert.AreNotEqual("AH", deck.Cards[0]);
  12:  }

Depending on what our rules are for testing and what our team thinks, this might be good enough. We also might go with something like this:
   1:  [TestMethod]
   2:  public void ShuffleShouldRandomizeADeckOfCards()
   3:  {
   4:      // arrange
   5:      var shuffler = new Shuffler();
   6:   
   7:      // act
   8:      var deck = shuffler.Shuffle();
   9:   
  10:      // assert 
  11:      Assert.AreNotEqual("AH", deck.Cards[0]);
  12:      Assert.AreNotEqual("AD", deck.Cards[13]);
  13:      Assert.AreNotEqual("AC", deck.Cards[26]);
  14:      Assert.AreNotEqual("AS", deck.Cards[39]);
  15:  }

We can make multiple assertions in a single unit test because we're ultimately testing the same thing: whether the deck is shuffled. Remember that at this point our code still looks like this:
   1:  public Deck Shuffle()
   2:  {
   3:      throw new NotImplementedException();
   4:  }

When our test runs, it will fail. Of course it will, we're not doing anything yet! Since we've achieved a red test, we need to make our test turn green.
   1:  public Deck Shuffle()
   2:  {
   3:      var deck = new Deck
   4:      {
   5:          Cards = new List<string>()
   6:      };
   7:   
   8:      deck.Cards.AddRange(new List<string> { "AS", "2S", "3S", "4S", "5S", 
               "6S", "7S", "8S", "9S", "10S", "JS", "QS", "KS" });
   9:      deck.Cards.AddRange(new List<string> { "AC", "2C", "3C", "4C", "5C", 
               "6C", "7C", "8C", "9C", "10C", "JC", "QC", "KC" });
  10:      deck.Cards.AddRange(new List<string> { "AD", "2D", "3D", "4D", "5D", 
               "6D", "7D", "8D", "9D", "10D", "JD", "QD", "KD" });
  11:      deck.Cards.AddRange(new List<string> { "AH", "2H", "3H", "4H", "5H", 
               "6H", "7H", "8H", "9H", "10H", "JH", "QH", "KH" });
  12:   
  13:      return deck;
  14:  }

Now our test passes, but this code isn't shuffling anything. This is probably the hardest part of doing TDD when you already have a proof of concept. We did the proof of concept so we'd know how to do what we want to do, but now we're essentially pretending that we don't know what we want to do. This is tricky, but it's important because by writing this code to turn our test green we've proven that our test isn't very effective. We're going to need some better tests, but remember that our tests shouldn't be more complicated than our code. We'll leave that first test in there for now since we know it passes and we'll add some additional tests, but we need to rename the test since it isn't really checking what the name says. Let's rename it to ShuffleShouldMoveAces. It's not a great name, but it's more descriptive of what's actually going on.

Now we can create another test named ShuffleShouldRandomizeADeckOfCards and do a more extensive check of the randomness of our deck of cards.
   1:  [TestMethod]
   2:  public void ShuffleShouldRandomizeADeckOfCards()
   3:  {
   4:      // arrange
   5:      var unshuffledDeck = new List<string>
   6:      {
   7:          "AH", "2H", "3H", "4H", "5H", "6H", "7H", "8H", "9H", "10H",
   8:          "JH", "QH", "KH", "AD", "2D", "3D", "4D", "5D", "6D", "7D",
   9:          "8D", "9D", "10D", "JD", "QD", "KD", "AC", "2C", "3C", "4C",
  10:          "5C", "6C", "7C", "8C", "9C", "10C", "JC", "QC", "KC", "AS",
  11:          "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S", "10S", "JS",
  12:          "QS", "KS"
  13:      };
  14:      var shuffler = new Shuffler();
  15:   
  16:      // act
  17:      var deck = shuffler.Shuffle();
  18:   
  19:      // assert
  20:      var numberOfMatches = 0;
  21:      for (var i = 0; i < 52; i++)
  22:      {
  23:          if (unshuffledDeck[i] == deck.Cards[i] ||
  24:              (i > 0 && deck.Cards[i-1] == unshuffledDeck[i]) || 
  25:              (i < 51 && deck.Cards[i + 1] == unshuffledDeck[i]))
  26:          {
  27:              numberOfMatches++;
  28:          }
  29:      }
  30:      Assert.IsTrue(numberOfMatches < 5,
  31:          $"{numberOfMatches} is not less than 5");
  32:  }


What we're doing here is checking whether each card in the shuffled deck is different than the card in the same position as the unshuffled deck, or the position just before it, or the position just after it. Since we know it's theoretically possible for a shuffled card to end up in the same spot in the deck, we've allowed that to happen with up to four cards and still have a passing test. With the code we have right now, this test fails. Now we can implement our proof of concept code to get make it green.
   1:  private readonly Dictionary<int, string> _unshuffledDeck =
   2:              new Dictionary<int, string>
   3:  {
   4:      {1, "AH"}, {2, "2H"}, {3, "3H"}, {4, "4H"}, {5, "5H"},
   5:      { 6, "6H"}, {7, "7H"}, {8, "8H"}, {9, "9H"}, {10, "10H"},
   6:      { 11, "JH"}, {12, "QH"}, {13, "KH"}, {14, "AD"}, {15, "2D"},
   7:      { 16, "3D"}, {17, "4D"}, {18, "5D"}, {19, "6D"}, {20, "7D"},
   8:      { 21, "8D"}, {22, "9D"}, {23, "10D"}, {24, "JD"}, {25, "QD"},
   9:      { 26, "KD"}, {27, "AC"}, {28, "2C"}, {29, "3C"}, {30, "4C"},
  10:      { 31, "5C"}, {32, "6C"}, {33, "7C"}, {34, "8C"}, {35, "9C"},
  11:      { 36, "10C"}, {37, "JC"}, {38, "QC"}, {39, "KC"}, {40, "AS"},
  12:      { 41, "2S"}, {42, "3S"}, {43, "4S"}, {44, "5S"}, {45, "6S"},
  13:      { 46, "7S"}, {47, "8S"}, {48, "9S"}, {49, "10S"}, {50, "JS"},
  14:      { 51, "QS"}, {52, "KS"}
  15:  };
  16:   
  17:  public Deck Shuffle()
  18:  {
  19:      var deck = new Deck
  20:      {
  21:          Cards = new List<string>(),
  22:          IsShuffled = false
  23:      };
  24:   
  25:      while (deck.Cards.Count < 52)
  26:      {
  27:          var random = new Random();
  28:          var position = random.Next(1, 53);
  29:   
  30:          if (!deck.Cards.Contains(_unshuffledDeck[position]))
  31:          {
  32:              deck.Cards.Add(_unshuffledDeck[position]);
  33:          }
  34:      }
  35:   
  36:      return deck;
  37:  }


And there we have it*. We took proof of concept code and ended up doing test-driven development with it.

* There is actually a better way to test the randomness of our Shuffle method, but we're going to cover that in a future blog post about the use of wrappers.

Thursday, April 11, 2019

Securing an Endpoint with an API Key

I've used API keys to access various 3rd party APIs in the past, but until recently I hadn't ever secured my own endpoint with an API key. Don't get me wrong, I've secured my endpoints in the past, just usually through the use of the [Authorize] attribute in .NET. Recently I encountered a situation where we needed to call an endpoint from an integration (SSIS) package that didn't have the opportunity to log in first. It quickly became obvious to us that the solution was to secure that particular endpoint in a different way. And here we are. This wasn't a difficult process, but it was kind of frustrating and it was actually pretty fun to implement so I wanted to keep track of the solution. Also, it's been a really long time since I posted so I figured it was time.

There are two parts to the solution. The first part - the caller (in our case an SSIS package, but it could be anything) - builds the API key and sends the request. The second part - the receiver (in our case a Web API endpoint) - receives the request and checks it for validity. There are a few things we considered when developing this solution.
  1. We needed to only allow requests from specific callers
  2. We needed to protect against replay attacks
  3. We needed to convey additional information in the request
After doing some research we came across Hash-based Message Authentication Code (HMAC) Authentication. It's basically a method for guaranteeing the information in the request via the use of an authentication header. (For more information on HMAC there's a pretty good blog post here.) There may be libraries out there to do this for us, but we couldn't find one we liked so we decided to roll our own.

Our HMAC Authentication header is going to have four parts to it: the ID of the caller, a time stamp, a random nonce value (a GUID), and the hashed (MD5), serialized (into JSON) content that we're sending to the server. The "content" here is the additional information we need to convey that I mentioned above.

The Caller

The first thing we do when creating the request is generate our content. In our particular case we're going to serialize, hash, and encode the content so that it can be included in the query string.
   1:  public string GenerateContent(string email, int id, string name)
   2:  {
   3:      var content = new SomeContent
   4:      {
   5:          Email = email,
   6:          Id = id,
   7:          Name = name
   8:      };
   9:  
   10:     var json = JsonConvert.SerializeObject(content);
   11: 
   12:     string contentAsBase64String;
   13:     using (var md5 = MD5.Create())
   14:     {
   15:         var encodedContent = Encoding.ASCII.GetBytes(json);
   16:         var md5Hash = md5.ComputeHash(encodedContent);
   17:         contentAsBase64String = Convert.ToBase64String(md5Hash);
   18:     }
   19: 
   20:     return contentAsBase64String;
   21: }


Now that we have the hashed, encoded contents that we're going to send to the endpoint we can build the full hmac header value. That's pretty easy with string interpolation.
   1:  var applicationId = "unicorns-and-puppies";
   2:  var timeStamp = DateTime.UtcNow;
   3:  var nonce = Guid.NewGuid();
   4:  var authenticationKey = $"{applicationId};{timeStamp.ToString("s")};{nonce};{contentAsBase64String}";


At this point we're going to create the request and add everything in as an authorization header. I'm including all of that code here, even though the mechanism for creating the request and adding the header can vary depending on which version of .Net you're using and any 3rd party libraries you might include.
   1:  var client = new HttpClient();
   2:  
   3:  var secretAsBase64 = Convert.FromBase64String("Some Randomly Generated String");
   4:  string hashedAuthenticationKey;
   5:  using (var hmac = HMACSHA512(secretAsBase64))
   6:  {
   7:      var authenticationKeyBytes = Encoding.UTF8.GetBytes(authenticationKey);
   8:      var hashedAuthenticationKey = hmac.ComputeHash(authenticationKeyBytes);
   9:      hashedAuthenticationKeyAsBase64String = Convert.ToBase64String(hashedAuthenticationKey);
   10: }
   11: 
   12: client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("hmac", authenticationKey);


We've added the header and now we want to create our body. What we're doing here is passing in the body with the content we want to pass in, and with the API key that we created just above. When the API receives the request we'll rebuild the API key and compare it to what's in the body here.

   1:  var body = new SomeRequest;
   2:  {
   3:      ApiKey = hashedAuthenticationKeyAsBase64String,
   4:      Content = json
   5:  };


And finally we can send the request.
   1:  var httpContent = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
   2:  
   3:  client.PostAsync("https://remote-endpoint.com/api/endpoint", httpContent);

The Endpoint

Now that we've sent the request, we have to receive it and validate it. When a .Net API receives a request there are different ways we can retrieve the data from the request. One common way is to use the FromBody and FromQuery attributes in the call signature. There's another attribute we're going to use to get the header, called FromHeader.

We'll get the body and the authorization header separately, validate the header pieces individually, then build the expected key the same way we did in the calling system and compare the expected key to the actual key to make sure they match.

   1:  public IActionResult Send([FromBody]SomeRequest something, [FromHeader(Name = "authorization")] string auth)
   2:  {
   3:      // check whether an authorization header exists
   4:  
   5:      var authorizationHeaderParts = authorizationHeader.Split(' ');
   6:      if (!authorizationHeader[0].Equals("hmac", StringComparison.OrdinalIgnoreCase))
   7:      {
   8:          // invalid request
   9:      }
   10: 
   11:     var authorizationPieces = authorizationHeaderParts[1].Split(';');
   12: 
   13:     if (authorizationPieces.Length != 4)
   14:     {
   15:         // invalid request
   16:     }
   17: 
   18:     // check whether authorizationPieces[0] is a valid application sending the request
   19: 
   20:     if ((DateTime.UtcNow - Convert.ToDateTime(authorizationPieces[1])).Seconds > 10)// we want the request to have been created less than 10 seconds ago to protect against replay attacks, but this length is arbitrary and could be lengthened or shortened based on need
   21:     {
   22:         // invalid request
   23:     }
   24: 
   25:     var applicationId = authorizationPieces[0];
   26:     var timestamp = authorizationPieces[1];
   27:     var nonce = authorizationPieces[2];
   28:     string contentAsBase64String;
   29:     using (var md5 = MD5.Create())
   30:     {
   31:         var content = Encoding.ASCII.GetBytes(something.Content);
   32:         var md5Hash = md5.ComputeHash(content);
   33:        contentAsBase64String = Convert.ToBase64String(md5Hash);
   34:     }
   35: 
   36:     if (!contentAsBase64String.Equals(authorizationPieces[3]))
   37:     {
   38:         // invalid request
   39:     }
   40: 
   41:     var authenticationKey = $"{applicationId};{timestamp};{nonce};{contentAsBase64String}";
   42: 
   43:     var secretAsBase64 = Convert.FromBase64String("Some Randomly Generated String");
   44: 
   45:     string hashedAuthenticationKeyAsBase64String;
   46:     using (var hmac = new HMACSHA512(secretAsBase64))
   47:     {
   48:         var authenticationKeyBytes = Encoding.UTF8.GetBytes(authenticationKey);
   49:         hashedAuthenticationKeyAsBase64String = Convert.ToBase64String(hashedAuthenticationKey);
   50:     }
   51:     if (!hashedAuthenticationKeyAsBase64String.Equals(something.ApiKey))
   52:     {
   53:         // invalid request
   54:     }


That's it! We created a request protected with an API key and then accepted the request and validated the API key. After looking this over again so I could post this entry I realize that it's probably more convoluted than it really needs to be. I think in the future if I have to do this again I'll use this code as the starting point, but definitely see where I can streamline it.