Skip to main content

Umbraco Package Migration to .NET Core: Criteria Providers - Migrating Tests

This is one of a series of posts looking at migrating Umbraco packages to V9 and .NET Core. Other posts in this series:

  1. Introduction
  2. A False Start
  3. A Clean Start - Controllers, Services, Configuration and Caching
  4. Criteria Providers - Working With HttpContext
  5. Leaning on Umbraco
  6. Migrating Tests
  7. Extension Methods
  8. Migrations
  9. Wiring It All Up
  10. Distributing and Wrapping Up

Adding a Tests Project

Having ported a reasonable amount of the functionality from the Personalisation Groups package over to a version for Umbraco V9 running on .NET Core, I've created a tests project and migrated over most of the existing unit tests.

There wasn't too much required here that wasn't fixed with some find and replace. I created an NUnit test project, which aligns with what Umbraco use in the CMS core, but that isn't necessary and you can use what you prefer. I'd previously used MSTest which still available in .NET Core. The only changes needed were changing the TestClass and TestMethod to TestFixture and Test respectively and amending some tests that used an ExpectedException attribute to instead use Assert.Throws(). I also added the Moq library from NuGet.

Now the package is using the standard pattern for configuration which is injecting a POCO representation of the configuration into classess that need it wrapped in an IOptions interface, I also need a way to make this available to test objects that depend on them when instantiated for test. This can be done via Options.Create(), as described by Mitch Valenta here.

I had one test that is probably trying to tell me I need to do some refactoring because I'm looking to test what probably should be a private method, which has been marked as internal to expose it for unit testing. But this kind of thing is sometimes needed, and in ASP.NET Framework we would add an attribute to indicate which other projects, such as test projects, should have access to be able to call internal methods. In .NET Core this information is added to the package .csproj project file:

  <ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
      <_Parameter1>PersonalisationGroups.Tests</_Parameter1>
    </AssemblyAttribute>
  </ItemGroup>

Most tests are now passing. The ones that aren't will need a bit of thinking about. I've got some code that scans the assemblies to look for personalisation criteria - all of which will implement the interface IPersonalisationGroupCriteria. The package does this to allow custom solutions, or other packages, to add their own additional criteria for their needs. It then uses a call to Activator CreateInstance to instantiate each criteria object. I'm running into a problem because, now I've switched to use dependency injection throughout, I no longer have a "parameterless constructor" for this method to use. Will park this for now though pending wiring up all the dependencies with the Microsoft DI abstraction IServiceCollection, from where hopefully there will be a way to resolve what's needed for each class.

Following Along

The repository containing the code for the migrated package is here. At the time of writing, the state of the migrated code can be seen using this link.

Comments