|Number of votes:||5|
This is a post in a series about testing and EPiServer. This post will cover some basic concepts as well as the tools we’re going to be using later on. I find that discussing naming style of tests, while important, can be as much of a productivity killer as a religious debate about prefix private variables with an underscore.
The point here is to recognize enough of the terms and tools so the following posts are possible to follow at least in theory.
The code we’re going to use as an example is the classic Add method in a calculator class.
Exiting stuff huh?
So, to write tests for this we’re going to be using NUnit. The easiest way to download NUnit is through NuGet. If you’ve installed it’s as simple as adding a package reference, search for Nunit and download it.
You can also get it from their homepage.
There are a few different schools on how to name your tests, how the tests should be written and such. I tend to follow the Arrange, Act, Assert (AAA) pattern.
Given the code above I’d like a test that verifies that our add method is capable of adding to numbers and returning the result. A test like that could look like this:
Unfortunately(? I don’t write too many classes like the calculator class. Especially not in an EPiServer project. More often than not you’re writing classes that have dependencies on other classes. I find that while it’s certainly possible to write unit tests without using mocking frameworks in practice it’s not something I’d recommended.
So when and why do you want to use mocks?
First scenario is that we have some code that’s depending upon our beloved friend HttpContext. In .Net 3.5 SP1 a few new classes were introduced that helps testing various http related classes. One of them is the HttpRequestBase class. HttpRequestBase defines virtual properties for all the properteries from HttpRequest and then you have HttpRequestWrapper that overrides all those properties and delegates them to the actuall HttpRequest object. Let’s say that we have a method that should behave differently depending on the value of a certain querystring.
Let’s say that we want to create the following tests
Given a querystring that does not contain a customer a specific exception is thrown
Given a querystring that contains a customer starting with a then a a grade customer is returned
Given a querystring that contains a customer not starting with a then a b grade customer is returned.
So, let’s start with the first test. We need to implement the abstract class HttpRequest and make sure that the QueryString property returns an empty name value collection. For the second test we need to return a customer starting with “a” and so on and so forth. This could look something like this:
With a test looking like this:
As you can imagine the amount of classes you have to create to satisfy the various test scenarios can become numerous. So, let’s see how these mocks can help us out.
I’m using the mocking framework called Moq. There are other frameworks out there so search around until you find one that suits you.
Again, the simplest way to download Moq is using NuGet but you can also download it from their homepage.
With Moq the basic flow for mocking classes like above is to create a moq of the type you want to mock.
You then instruct Moq on what should happen when someone interacts with the mocked object.
To actually use the object we pass in the Object property of the mocked object. So when we create a new instance of Mock<T> the resulting type is a Mock of T and the property Object is of type T.
So instead of creating tailored classes we create the behaviors we want on the fly.
Moq acts as a proxy around your mocked type so it needs to be able to override the member you setup. So, abstract or virtual members makes Moq happy. The virtual part has been something of a hot potato in .Net in general. As I’m sure you’re aware virtual is default in Java but not in .Net. Making more members virtual in the EpiServer code base would surely improve testability so I’ll just leave this message from “The virtual boys” (and yes, being able to lean your head like that is a requirement for joining “The virtual boys”).
Another usage scenario is when you want to verify that objects interacts with each other in a specific way.
Let’s say we have some code that changes the name of a PageData object according to some business rule and then saves it. Since you do your best of following the SOLID principles you have one class that changes the name (and nothing more) and then a façade that used that class as well as saving the page through the data factory.
The important part here is that you do not care what the Save method does, you only want to make sure that it is being called. Likewise you don’t care about the logic performed in the ShouldChangeName and the GenerateNewName methods.
This is somewhat of a pattern in how I work nowadays. Write small, specific classes with accompanying tests and then facades with tests for the integration of those classes it depend on. In this case we would have tests for SomePageThing that verifies that the methods ShouldChangeName and GenerateNewName do what they are supposed to do but in the context of testing the façade class we really don’t care. What we do care about is that if the ShouldChangeName method returns true it should set the PageName on the page data object and then save it.
Let’s walk though this step by step.
We create a PageData object and the mocked objects we need as well as the facade itself.
Next we need to setup out SomePageNameThing mock so that it behaves the way we need to for this this. First of we need to make sure that the call to ShouldChangeName returns true. We must also make sure that the call to GenerateNewName returns some string.
To finish we need to write our act and assert.
In much the same way we can verify that the save method is being called on the datafactory façade.
Note that we use the Verify method on the moq to do this verification. As you can imagine being able to mock various EPiServer classes like this makes it so much easier to test scenarios where you need to interact with EPiServer in one way or another.
So hopefully this post will make the following discussion about hot to make EPiServer code testable will make more sense. The next post will focus on the steps taken to test the fallback language functionality.