|

How To Create A C# Unit Test In Visual Studio

How To Create A C# Unit Test In Visual Studio

Any time you are writing some software, you probably often find yourself reaching a certain point and then building and running the program to see if things work. As more and more code piles up, it becomes very time-consuming to run and inspect the results yourself. In C# and Visual Studio, it is possible to set up automated testing by way of Unit Tests. A unit test is simply when a developer writes some C# code to test other C# code in an automated fashion. In this tutorial, we’ll take a look at the very basics of setting up a unit test in Visual Studio.


Unit Test Project (.NET Framework)

There is a project type in Visual Studio that is dedicated to creating tests. This is appropriately named the Unit Test Project. We would want to use this type of project to create tests that verify the classes we build work as intended. The unit test project type creates a new assembly with the test code we write. That new assembly will reference another assembly with the code that is being tested. If we want to verify that our StockPortfolio.cs class is working correctly, we create a new test project and write some test code where that test project will reference the assembly with the StockPortfolio. Let’s add a new project in our solution to show this technique. To start, right-click in the solution explorer window on the name of the solution. This will bring up a new sub menu where you can choose Add->New Project.
new project from solution explorer

Once there, now you would choose the Test option under the Visual C# area, choose Unit Test Project (.NET Framework), and give the new project a name.
add new project unit test

Once clicking OK, you’ll notice that the solution explorer in Visual Studio now has two projects in it. The original one, and the new test one that was just created.
new test project in solution explorer

Inspecting the new Stocks.Test project reveals a new Class file named UnitTest1.cs which has this boilerplate code set up for you.


Running The Tests

Now when you build the solution, what happens is both projects contained in the solution get built at the same time. In our case that means both the Stocks and Stocks.Test projects get built. Let’s build it just for kicks now by clicking Ctrl+Shift+B. Sure enough, this is the output we get.

1>------ Build started: Project: Stocks, Configuration: Debug Any CPU ------
2>------ Build started: Project: Stocks.Test, Configuration: Debug Any CPU ------
2>  Stocks.Test -> C:\Users\user\source\repos\Stocks\Stocks.Test\bin\Debug\Stocks.Test.dll
1>  Stocks -> C:\Users\user\source\repos\Stocks\Stocks\bin\Debug\Stocks.exe
========== Build: 2 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

So we now have a Stocks.exe assembly and a Stocks.Test.dll assembly. We learned about the different types of assemblies on our assemblies tutorial. We can even run the tests right away. We don’t yet have any tests that test any valid logic, but that initial boilerplate code is in fact a test. We can select Test->Run->All Tests to see what happens.
visual studio test run all tests
The output window shows us what Visual Studio is doing.

[2/11/2019 11:19:41 AM Informational] ------ Discover test started ------
[2/11/2019 11:19:46 AM Informational] ========== Discover test finished: 1 found (0:00:04.8223994) ==========
[2/11/2019 11:19:46 AM Informational] ------ Run test started ------
[2/11/2019 11:19:49 AM Informational] ========== Run test finished: 1 run (0:00:02.5658109) ==========

Then, in the GUI of visual studio we can see a new window, the Test Explorer window.
test explorer window visual studio

In the Test Explorer there’s a single method named TestMethod1. We can see a green check mark which must mean good news. Well, it means the test passed! It passed because we’re not really testing any functionality yet but we will soon enough.


Structure Of A Unit Test

Inspecting that Stocks.Test project shows us a file named UnitTest1.cs. Inside that file is a class of the same name, UnitTest1. Finally, we see a method inside that class with the name of TestMethod1. Just earlier we looked at the boilerplate code that was produced for us. There is a peculiar syntax we see in there where we see both [TestClass] and [TestMethod]. What are those?

Those names in brackets tell the test runner which classes and methods are actually tests. These should be executed during testing to see if they pass or fail and the square bracket syntax is known as attributes in C#. An attribute is a piece of data that is associated with a class or a method. They can be used for many things, but when setting up tests it is important to remember that when writing a test that the test runner will run for you, you’ll need to place that code inside of a method that has a TestMethod attribute which uses square brackets around it. Additionally, the class that the test method resides in must be a public class that has the TestClass attribute as well.


Introducing Assert

The Assert class is where you can start working with actual logic. You can use the Assert class to make assertions against data in the program. If those assertions don’t come back true, then the test will fail with an error. The Assert class has a large collection of methods for testing such as AreEqual, AreNotEqual, AreNotSame, AreSame, Equals, Fail, Inconclusive, IsFalse, IsInstanceOfType, IsNotInstanceOfType, IsNotNull, IsNull, IsTrue, ReplaceNullChars, ThrowsException, and ThrowsExceptionAsync. Let’s try one out. We are going to try to assert that 1 is equal to 2.

We can now run all the tests and of course, Visual Studio shows us that we have failing tests.
visual studio unit test failing

Once you see that failing test, you can drill right down on the failing test method and get some information about it. Right here we click on the TestMethod1 to get the information that Message: Assert.AreEqual failed. Expected:<1>. Actual:<2>. So the test makes clear what was expected, and what actually happened. You can also double-click the failing method in the test explorer window and visual studio will automatically move the cursor to the location in the test code where the failure happened.
double click to move to method

Let’s make that test pass now. We can assert that 1 is equal to 1. We fully expect this to pass when we run all tests now.

TestMethod1 Passing


Testing The StockPortfolio Class

Ok the information above got us up and running with how to actually create a test in Visual Studio. We now know how to create a new project in a solution for testing purposes, how to identify tests with the Test Attribute syntax, and how to run the tests. Cool. Now let’s make some tests that determine if the StockPortfolio class in our project is working correctly. We can do that by right clicking on the Stocks.Tests project and choosing to add a class. We can name it StockPortfolioTests.
new class test file

This will create some boilerplate testing code, but we still have to label the class as a test class with the [TestClass] attribute and to do so, Visual Studio will nudge you to import the Microsoft.VisualStudio.TestTools.UnitTesting namespace.
Quick Actions Tooltip

Now our code is ready to start adding tests using the Microsoft.VisualStudio.TestTools.UnitTesting namespace.


References And Access Modifiers

In order to test the StockPortfolio class, we need to use it in our Stocks.Test project. When we try to use it, we get this error: “The name ‘StockPortfolio’ does not exist in the current context”.
The name stockportfolio does not exist in the current context

Ok so what happened? Even though our two projects are in the same solution, we will not be able to use StockPortfolio until a reference is established from the Stocks.Test project to Stocks.
We can fix this by right-clicking References->Add Reference->Projects and then selecting Stocks. This allows us to reference the assembly that is created by the other project, the Stocks assembly. Once this is done, we see the Stocks assembly show up in the Solution Explorer.
reference assembly from different project same solution

That’s great, but now we get a different error message of “StockPortfolio is inaccessible due to its protection level”.
stockportfolio is inaccessible due to its protection level

To fix this, we can change the access modifier of the StockPortfolio Class. When creating a class, if you don’t specify the access level, its default will be set to internal. An internal class can only be used by code that is inside of the same project. If I want to make StockPortfolio available in StockPortfolioTests, it needs to be set to public.

This is great, but now we are getting an error in this class: “Inconsistent accessibility: return type ‘StockStatistics’ is less accessible than method ‘StockPortfolio.ComputeStatistics()'”.
inconsistent accessibility return type stockstatistics is less accessible than method stockportfolio-computestatistics

Why is this? This is because the StockPortfolio class is leveraging another class, StockStatistics, and it’s access modifier is also internal. We can fix this in the StockStatistics class my making it public like so.

This should now fix everything we need to create a useful test. We can craft a test to make sure that when we feed the StockPortfolio a collection of stock prices, it will correctly calculate and return the lowest stock price when we ask for it. Here is the code to do that.

Let’s walk through it.

  • A new StockPortfolio object is instantiated and placed in the portfolio variable.
  • Using that variable, we now call the AddStock() method two times. Once to add a price of 100, and another to add a price of 25.
  • Again from the portfolio variable, we now call the ComputeStatistics() method and store the result in the result variable.
  • We can then assert that 25 is equal to calling result.LowestStock.

Looks like the test is passing!

From here we can continue to add tests as we like and as needed to provide the correct amount of code coverage.


How To Create A C# Unit Test In Visual Studio Summary

In this tutorial about testing in C#, we first reviewed how C# creates an assembly when building a solution in Visual Studio. The resulting assembly shares the name of the project and has a .exe or a .dll extension. The first is an executable file, and the next is a class library. In order to verify that your code is performing as you would expect, you can create and run unit tests in Visual Studio. Unit testing is the process of breaking down a program into isolated actions that you can test as individual units. The Test Explorer is where we can view our tests and run them in Visual Studio. In order to make use of the methods available for testing, we made use of the Microsoft.VisualStudio.TestTools.UnitTesting namespace. It is wise to rerun unit tests anytime changes are made to the code in a program. This will ensure that new code does not affect existing code and the program continues to work as expected.