April 20th, I presented a webinar on JustMock, showing off the Free Edition as well as the Commercial Edition features. The source code for the webinar is available from here, and the video recording of the webinar is available on Telerik TV.
In addition to JustMock for mocking, the test frameworks that I used in the webinar are NUnit and NUnit.Should. Since I’ve had several questions about how to get started with these tools, I will show how to setup a test project and execute some initial tests.
The easiest way to add references is through NuGet. NuGet is a Visual Studio Extension that allows for quickly adding in required dependencies into your projects. More information can be found here.
Create a Test Project
Once you have NuGet installed, create a new project in Visual Studio. I usually chose Windows->Class Library, since we don’t need to have any interaction with a user or the console. Assign the project a name, select Create New Solution (the default) and optionally change the Solution Name.
In solution explorer, you will see your newly created project with the descriptively named “class1.cs”. Go ahead and delete this class, as we will be adding new classes that are more meaningful.
Add Required Dependencies
In solution explorer, right click on the “References” folder to get the following context menu:
Alternatively, you can select Tools->Library Package Manager–>Add Library Package Reference from the main Visual Studio Menu.
We will start with adding NUnit.Should, which contains a set of extension methods to make NUnit tests cleaner. One of the great things about NuGet, is that the packages (assuming they are setup correctly) will also bring into your project all of the required assemblies. So by selecting NUnit.Should, we will get NUnit as well!
Click on install, and it will add reference for both NUnit and NUnit.Should into your project, copy the assemblies to a folder called “packages” off the solution root, and add a file into your project “packages.config”. This file contains information about the packages that were installed via NuGet.
For JustMock, follow the exact same process. This will download the Free Edition of JustMock into your project, as well as a text file that contains more information on where to find documentation for JustMock.
When complete, if you select Add Library Package Reference again, and select Recent Packages, you will see a window that looks like this:
NOTE: For JustMock, this installs only the Free Edition. For the commercial edition, please see http://www.Telerik.com/mocking to download a fully functional trial version. If you are adding a reference to the Commercial Edition, you would add the reference the “traditional” way – right click the references folder, select Add a reference, and then browse to the install location for JustMock and add the reference to Telerik.JustMock.dll.
Initial Unit Tests
Arrange, Act, Assert
The best way to construct a unit test is using the Arrange, Act, Assert paradigm. The premise for this pattern is to first setup up all of the items that are required for your system under test (Arrange), execute the action to be tested (Act), and then assert the results (or non-results) of that action (Assert).
Creating the First Unit Test
Add a class to the project, and call it “LoginTests.cs”. NOTE: By convention in Test Driven Development, classes are named after the objects that they are testing. In this example, we will be creating a Login class to handle user authentication into an imaginary system.
We have to indicate to the unit testing framework that this class is a test fixture. In NUnit, we do this with .NET attributes. Make the class “public'” and add the [TestFixture] attribute. You will have to add the using statement NUnit.Framework to the top of your class. NOTE: In some testing frameworks, this attribute has been made optional. I recommend still using the attribute for the sake of readability.
The next step is to add a test. Again, this is done with decorating a method with an attribute, and for NUnit that is the [Test] attribute. A test is a public void method that doesn’t take parameters (NOTE: there are data driven tests that do take parameters, as shown later in this post). The test method should be named for what it test. There are several schools of thought on this, but I prefer the simple approach of “Should_Do_Something”. For this test, we are testing that the user is validated against the authentication system, so “Should_Validate_User” should do nicely. My personal preference is to add underscores between the words for readability, but that is also a hotly debated topic.
Finally, you will end up with code like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
namespace MyFirstUnitTests
{
[TestFixture]
public class LoginTests
{
[Test]
public void Should_Validate_User()
{
}
}
}
We then flush out the body of the unit test. The test that we are going to write is to make sure that the SecurityHandler class actually calls into the UserValidationSevice to verify the user’s credentials. None of these classes are written yet, so we will start from scratch in true TDD (Test Driven Development) fashion.
Our SecurityHandler class will take an instance of IUserValidationService through constructor injection. To set this up, we need to have an actual instance (funny how .NET requires that). This is where JustMock comes in. We need to create a mock of the service, and then set up expectations on the service (for more detail on using JustMock, please refer to my other blog post series on JustMock).
string userName = "Bob";
string password = "Foo";
IUserValidationService service =
Mock.Create<IUserValidationService>();
service.Arrange(x => x.ValidateUser(userName, password))
.Returns(true).Occurs(1);
Using JustCode’s refactoring capabilities, we flush out the IUserValidationService interface to this:
public interface IUserValidationService
{
bool ValidateUser(object userName, object password);
}
The next step is to create an instance of the System Under Test, in this case the SecurityHandler class.
SecurityHandler handler = new SecurityHandler(service);
This completes the “Arrange” part of our Unit Test.
Now, we need to code the “Act”:
bool result = handler.LoginUser(userName, password);
Again, using JustCode to create the missing objects, and coding the obvious implementation into the SecurityHandler class, we end up with this for our System Under Test:
public class SecurityHandler
{
private readonly IUserValidationService _service;
public SecurityHandler(IUserValidationService service)
{
_service = service;
}
public bool LoginUser(string userName, string password)
{
return _service.ValidateUser(userName, password);
}
}
Finally, we need to assert that we get the expected results:
Assert.IsTrue(result);
result.ShouldBeTrue();
service.Assert();
The first two lines do the exact same test. The standard NUnit way of asserting values is with the Assert class which exposes a lot of ways to test. The second line is enabled though the NUnit “Should” extensions, which in my opinion, makes the assertion more readable.
The last line asserts that the Mock behaved as we expected it to.
The next code block takes advantage of the TestCase feature in NUnit, which allows for data driven tests. This allows for testing multiple Use Cases with the same test, reducing lines of code, and increasing test Fidelity. In a real system, we would want the SecurityHandler to behave differently with a failed login (such as logging the failed attempt, or throwing and exception), but in this simple example, it just passes through the result of the validation call. For more detailed examples, please refer to me blog series on JustMock, where I show extensive examples of testing with JustMock.
using NUnit.Framework;
using Telerik.JustMock;
using Telerik.JustMock.Helpers;
namespace MyFirstUnitTests
{
[TestFixture]
public class LoginTests
{
[TestCase("Bob", "Foo", true)]
[TestCase("Bob", "Bar", false)]
public void Should_Validate_User(
string userName, string password, bool expectedResult)
{
IUserValidationService service =
Mock.Create<IUserValidationService>();
service.Arrange(x => x.ValidateUser(userName, password))
.Returns(expectedResult).Occurs(1);
SecurityHandler handler = new SecurityHandler(service);
bool result = handler.LoginUser(userName, password);
Assert.AreEqual(expectedResult, result);
result.ShouldEqual(expectedResult);
service.Assert();
}
}
public class SecurityHandler
{
private readonly IUserValidationService _service;
public SecurityHandler(IUserValidationService service)
{
_service = service;
}
public bool LoginUser(string userName, string password)
{
return _service.ValidateUser(userName, password);
}
}
public interface IUserValidationService
{
bool ValidateUser(object userName, object password);
}
}
Hopefully that get’s you started down the path of effective unit testing!
Happy coding!