Unit Testing Sitecore Components Part 4: Mocking Items and Fields
In the previous posts of this series, I’ve refactored an existing Sitecore component to make it’s logic more reusable and prepare the component and the logic it includes for unit testing. In this post I’ll be writing the unit tests for the refactored EntryTaxonomy
class, showing how to mock items and field values.
This post is part of a series covering the principals I showed during my virtual SUGCON presentation on unit testing Sitecore components in April of this year (2020). The following is a list of the posts belonging to the series so far, along with the principals covered in the post:
Post not found: logicless-view-itemless-model- Principal: Keep business logic out of the view.
- Principal: Keep
Item
out of the model.
- Principal: Encapsulate logic.
- Principal: Use Dependency Injection and Abstractions
- Principal: Avoid implicit data
- Principal: Use Sitecore Abstractions
- Recap
- Resources
In this post, I’ll be showing:
- How to mock the
Sitecore.Data.Items.Item
class. - How to mock field values of a mocked item.
Mocking an Item
I’ve already shown how to mock an item in part 2 of this series: Post not found: encapsulate-logic. To save repeating the mocking code over and over, I encapsulated the code in a method on the test class. Here’s the method for reference:
1 | private Item CreateItem() |
The class I need to test is the EntryTaxonomy
class which was completed in part 3 of this series: Post not found: avoid-static-members. Here’s the class for reference:
1 | public class EntryTaxonomy : IEntryTaxonomy |
Only having the ability to mock Item
won’t get me very far in testing the GetCategories
method beyond checking the guard clauses. And you might notice that I don’t have any of those, so I’ll start there:
1 | public class EntryTaxonomyTests |
Both those tests will fail, because I’m currently missing guard checks for the parameters. I’ll update EntryTaxonomy
to validate the parameters:
1 | public class EntryTaxonomy : IEntryTaxonomy |
Inspecting the code for the GetCategories
method I can see a couple of tests I want to write:
- Item doesn’t reference any categories
- Item references 1 or more categories
But the current CreateItem
method I have is quite limited and can’t mock field values. So I’ll fix that…
Mock Item Field Values
You’ll see in the EntryTaxonomy
class above I’m accessing the Category
field through the Fields
property of the Item
. This is because I want to access the field as a MultilistField
instance and not just get the string value of the field, which I would get if I used the indexer on the Item
instance. The Fields
property is of type FieldCollection
. Your first instinct may be to simply instantiate a new FieldCollection
instance for use in the test. But FieldCollection
is not just a simple collection class, and it will use the static Sitecore methods to resolve things like templates when accessing fields, so it will be easier for the test if I mock this class as well.
1 | private Item CreateItem() |
With this updated method I can now write the first test case from above, to validate when the item doesn’t reference any categories.
1 | public class EntryTaxonomyTests |
The next test case requires I set the value of the Category
field on the item. To do so, all I need to do is mock the field and add it to the existing fields mock instance. Rather than bundling all that into the existing method, I’ll create a new test utility method to mock the field and add it.
1 | private void SetItemField(Item item, string fieldName, string fieldValue) |
A multilist field in Sitecore is a pipe separate list of IDs of the items being referenced. As part of the “arrange” part of the test I’ll also need to create the category items. You’ll notice in the implementation of the GetCategories
method that I’m using the GetItems
method on the field instance, which resolves the items using the Database
property of the field instance. So to be able to make sure my mocked items are returned, I’ll need to mock the Database
property of the field instance and set it up to return any of the items which I’ve mocked. That will require a few updates to the CreateItem
test utility methods.
1 | private Item CreateItem(Database database = null) |
I’m almost ready to write that last test case. But I have one more update to make before I can. Looking over the GetCategories
method, the last thing I’ll need to be able to do is use the item indexer to access the Title
field of the mocked category item instances.
1 | private void SetItemField(Item item, string fieldName, string fieldValue) |
Now I’m ready to write that last test.
1 | public class EntryTaxonomyTests |
Conclusion
And there we have it! The EntryTaxonomy
class is now fully unit tested by mocking the Sitecore data classes. It’s nice and lightweight and doesn’t require a running Sitecore instance to run.
Comments are closed
loading...