Categories
Uncategorized

Unit Testing Your ScriptLink API with C# and MSTest

In my previous articles, we setup SoapUI and Postman to test the responses to our submissions. While this is an important testing method, it is time consuming and can be difficult to test all the various scenarios. This where Unit Testing comes in. With Unit Tests we can test our code for regressions in seconds (or milliseconds) and as we write our code.

In my previous articles, we setup SoapUI and Postman to test the responses to our submissions. While this is an important testing method, it is time consuming and can be difficult to test all the various scenarios. This where Unit Testing comes in. With Unit Tests we can test our code for regressions in seconds (or milliseconds) and as we write our code.

Unfortunately, the design we have followed so far does not support Unit Testing, so we will have to make some changes. The best practice is to write your test, then write your code (make your code changes). So that is what we are going to do.

Add a Unit Test Project

Ok. Let’s get started.

  1. Launch Visual Studio.
  2. Open our ScriptLink demo solution.
  3. Right-click on the solution and select Add->New Project.
  4. Set the Language filter to C# and the Project Type filter to Test.
  5. Select Unit Test (.NET Framework) and select Next.
Screenshot of selecting a Unit Test project to add in Visual Studio.
Adding a Unit Test project in Visual Studio
  1. Name the project.
    Common naming patterns use the name of the project you are testing appended with “.Tests” Mine will be RS.ScriptLinkDemo.Soap.Tests.
  2. Select Create.
Screenshot of Configuring a new .NET Framework Unit Test Project
Configuring a new .NET Framework Unit Test Project

You should now have a Unit Test project added to your solution with a sample Unit Test (UnitTest1.cs) open and ready to edit. Go ahead and delete UnitTest1.cs. We will be walking through the creation of each test.

Screenshot of Unit Test Project added to ScriptLink solution
Unit Test Project added to ScriptLink solution

Add References

  1. Right-click on References and select Add Reference…
  2. Select both of the projects listed from our solution.
Screenshot of Unit Test project referencing ScriptLink web app and class library
Unit Test project referencing ScriptLink web app and class library

Create Our First Unit Tests

Our GetVersion Test

The first thing we are going to do is create our Unit Tests for both GetVersion and and the HelloWorld response to RunScript.

  1. Right-click on the Unit Test project and select Add->Unit Test…
  2. If you deleted the previous Unit Test you should see a new UnitTest1.cs file created and opened for editing.
  3. Right-click on the UnitTest1.cs file and select Rename.
  4. Set the name to GetVersion and press Enter.
  5. Select Yes when prompted.
Screenshot of renaming the default Unit Test file in Visual Studio
Renaming the default Unit Test file in Visual Studio
  1. Now let’s create our Unit Test.
  2. In general, Unit Tests have three steps:
    1. Arrange (Setup the scenario to test)
    2. Act (Run the method to be tested)
    3. Assert (Verify the method returns as expected)
  3. Rename TestMethod1() to Execute_GetVersion_ReturnsString().
  4. Add the following steps to the test.
[TestMethod]
public void Execute_GetVersion_ReturnsString()
{
    // Arrange
    string expected = "v.0.0.1";

    var command = new GetVersion();

    // Act
    var actual = command.Execute();

    // Assert
    Assert.AreEqual(expected.GetType(), actual.GetType());
}
  1. You should see a compile error because we have not created the GetVersion class yet. This is intentional as best practice is to write your test first then write your code.
  2. Ok. Let’s create our HelloWorld Unit Test.
    Note: Eventually we will be setting up our ScriptLinkController to call different commands based on the parameter provided. This is why we are creating a test specifically for HelloWorld rather than generally for RunScript.
  3. Right-click on the Unit Test project and select Add->Unit Test…
  4. Right-click on UnitTest1.cs and select Rename.
  5. Set the name to HelloWorld and press Enter.
  6. Select Yes when prompted.
  7. Rename TestMethod1() to Execute_HelloWorld_ReturnsOptionObject2015().
  8. Add the following steps to the test:

Our HelloWorld Tests

Ok. Let’s create our HelloWorld Unit Test. Note: Eventually we will be setting up our ScriptLinkController to call different commands based on the parameter provided. This is why we are creating a test specifically for HelloWorld rather than generally for RunScript.

  1. Right-click on the Unit Test project and select Add->Unit Test…
  2. Right-click on UnitTest1.cs and select Rename.
  3. Set the name to HelloWorld and press Enter.
  4. Select Yes when prompted.
  5. Rename TestMethod1() to Execute_HelloWorld_ReturnsOptionObject2015().
  6. Add the following steps to the test:
[TestMethod]
public void Execute_HelloWorld_ReturnsOptionObject2015()
{
    // Arrange
    OptionObject2015 expected = new OptionObject2015();

    OptionObject2015 optionObject2015 = new OptionObject2015();
    string parameter = "";
    var command = new HelloWorld(optionObject2015, parameter);

    // Act
    var actual = command.Execute();

    // Assert
    Assert.AreEqual(expected.GetType(), actual.GetType());
}
  1. Let’s add another test to verify that the ErrorCode is returned as expected.
[TestMethod]
public void Execute_HelloWorld_ErrorCodeEquals3()
{
    // Arrange
    double expected = 3;

    OptionObject2015 optionObject2015 = new OptionObject2015();
    string parameter = "";
    var command = new HelloWorld(optionObject2015, parameter);

    // Act
    var actual = command.Execute();

    // Assert
    Assert.AreEqual(expected, actual.ErrorCode);
}

We should now have three unit tests defined and listed in our Test Explorer. These test essentially fail because the code cannot currently compile. So let’s write our code.

Create Our Commands

To make our web service be available for unit testing we are going to pass on the functionality of the API to separate public classes.

  1. Right-click on the Web Application project and select Add->New Folder.
  2. Name the folder Commands and press Enter.
  3. Now we can create our classes.

Create the GetVersion Command

Now we will add our GetVersion Command.

  1. Right-click on the Commands folder and select Add->Class…
  2. Set the name to GetVersion.cs and select Add.
  3. Add a public method called Execute() and set it to return our version string. I incremented it to v.0.0.2 so we can see the difference in the end.
public class GetVersion
{
    public string Execute()
    {
        return "v.0.0.2";
    }
}

Create the HelloWorld Command

Next, we will add our HelloWorld command.

  1. Right-click on the Commands folder and select Add->Class…
  2. Set the name to HelloWorld.cs and select Add.
  3. Add a protected OptionObject2015 property named OptionObject2015.
  4. Be sure to add the using for our class library. In my case it is RS.ScriptLinkDemo.Objects.
  5. Add a protected string property named Parameter.
  6. Add a constructor that will take the received OptionObject2015 and parameter and assign them to our protected properties.
  7. Add a public method named Execute() and set it to return an OptionObject2015 with the ErrorCode 3 and the ErrorMesg “Hello, World!”
  8. Here is our full class.
public class HelloWorld
{
    private OptionObject2015 _optionObject2015;
    private string _parameter;

    public HelloWorld(OptionObject2015 optionObject2015, string parameter)
    {
        _optionObject2015 = optionObject2015;
        _parameter = parameter;
    }

    public OptionObject2015 Execute()
    {
        OptionObject2015 returnOptionObject = new OptionObject2015()
        {
            EntityID = _optionObject2015.EntityID,
            EpisodeNumber = _optionObject2015.EpisodeNumber,
            ErrorCode = 3,
            ErrorMesg = "Hello, World!",
            Facility = _optionObject2015.Facility,
            NamespaceName = _optionObject2015.NamespaceName,
            OptionId = _optionObject2015.OptionId,
            OptionStaffId = _optionObject2015.OptionStaffId,
            OptionUserId = _optionObject2015.OptionUserId,
            ParentNamespace = _optionObject2015.ParentNamespace,
            ServerName = _optionObject2015.ServerName,
            SystemCode = _optionObject2015.SystemCode,
            SessionToken = _optionObject2015.SessionToken
        };

        return returnOptionObject;
    }
}

Update Our Test Usings

We should now have our two commands create and still have the three compile errors from our Unit Tests. We need to go back to our Unit Tests and add our using for the the Commands namespace.

Screenshot of creating HelloWorld Command in Visual Studio
Creating HelloWorld Command in Visual Studio
  1. Open our GetVersionTests.cs file from the Unit Test project.
  2. Add a using for our Commands namespace. Mine is RS.ScriptLinkDemo.Soap.Commands;
  3. Do the same for our HelloWorldTests.cs file.
  4. Our compile errors should now be gone.
Screenshot of ScriptLink Unit Tests Ready to Run
ScriptLink Unit Tests Ready to Run

Run Our Tests

Now that our code should be able to compile lets run our tests and see if they pass.

  1. In our Test Explorer panel, select the Run All Tests icon.
  2. This should compile the code and run the tests. If all is well all three tests should have passed.
Screenshot of ScriptLink Unit Tests Passing
ScriptLink Unit Tests Passing

Update Our Web Service

Now that our tests are passing, let update our Web Service to use our new commands instead.

  1. Open our ScriptLinkController in the web application project.
  2. Add a using for our Commands namespace. Mine is RS.ScriptLinkDemo.Soap.Commands.
  3. Update each web method to instantiate the desired command and execute it.
[WebMethod]
public string GetVersion()
{
    var command = new GetVersion();
    return command.Execute();
}

[WebMethod]
public OptionObject2015 RunScript(OptionObject2015 optionObject2015, string parameter)
{
    var command = new HelloWorld(optionObject2015, parameter);
    return command.Execute();
}
  1. At this point I like to run my unit tests again to verify the solution compiles and everything is still Ok.

Verify Web Service is Working

Since we modified our Web Service and that is not tested by the Unit Tests, let’s use SoapUI or Postman to verify the API still responds as expected. I am going to use SoapUI in the steps below.

  1. Run the debugger for our web application.
  2. Open SoapUI.
  3. Expand your ScriptLink demo project so you can see each request.
  4. Open and run the GetVersion request.
  5. If everything is correct you get the version number as entered in the command.
Screenshot of SoapUI Test Showing Expected GetVersion Response
SoapUI Test Showing Expected GetVersion Response
  1. Open and run the RunScript Default request.
  2. If everything is correct, you should get the expected ErrorCode 3 and ErrorMesg “Hello, World!”
Screenshot of SoapUI Test Showing Expected RunScript Response
SoapUI Test Showing Expected RunScript Response

We’re All Set

We have accomplished a lot with these changes.

  • We have abstracted our code to minimize the number of edits required to our web service. We will still have to edit it if we want it to do more than HelloWorld. Any edits to HelloWorld should not require any changes to the web service (asmx).
  • We have created unit tests to monitor for regressions in our codes. For example, GetVersion should always return a string though we don’t care what the current version number is.
  • We have used our external API testing applications (SoapUI or Postman) to verify our API still works as expected.

We are now in great shape to iterate on our code to add functionality and verify everything still works. Next week, we will setup our controller to be able to change behavior based on the parameter supplied.