Posts tagged ‘C#’

I have just recently discovered the [TestCase] attribute of NUnit. With careful use it can drastically reduce the number of test methods you need to write. For my needs on a recent project I wanted to check field values which were being pulled from my database. What I’ve come up with is a simple extension to the NUnit Assert class which allows me to write test code such as …

[TestCase(0, "Forename", "Antony")]
[TestCase(0, "Surname", "Scott")]
[TestCase(0, "TwitterUserName", "antony_scott")]
public void ExampleTest(int index, string fieldname, object expectedValue)
{
    var result = GetPersonDetails();
    var list = result.ToList();
    Assert.IsFieldEqual(list.ElementAt(index), fieldname, expectedValue);
}

This gives me a very compact and easy to understand test with great visibility of any fields which are being pulled from the database correctly. All this is nothing new, as I’ve blogged about it previously here.

What I’ve added is the ability to dig into a structure like so …

[TestCase(0, "Forename", "Antony")]
[TestCase(0, "Surname", "Scott")]
[TestCase(0, "Twitter.UserName", "antony_scott")]
public void ExampleTest(int index, string fieldname, object expectedValue)
{
    var result = GetPersonDetails();
    var list = result.ToList();
    Assert.IsFieldEqual(list.ElementAt(index), fieldname, expectedValue);
}

In case you can’t see any difference, it’s the “dot” in the 3rd test case.

Here is the “extension” of the Assert class which makes it possible …

    public class Assert : NUnit.Framework.Assert
    {
        public static void IsFieldEqual(object obj, string propertyName, object expectedValue)
        {
            var type = obj.GetType();

            var dotIndex = propertyName.IndexOf('.');
            if (dotIndex != -1)
            {
                var innerObjName = propertyName.Substring(0, dotIndex);
                var innerPropName = propertyName.Substring(dotIndex + 1);
                var innerProp = type.GetProperty(innerObjName);
                var innerObj = innerProp.GetValue(obj, null);
                IsFieldEqual(innerObj, innerPropName, expectedValue);
            }
            else
            {
                var prop = type.GetProperty(propertyName);
                var actualValue = prop.GetValue(obj, null);
                AreEqual(expectedValue, actualValue);
            }
        }
    }

Actually generating the schema is pretty simple …

using Newtonsoft.Json.Schema;

var jsonSchemaGenerator = new JsonSchemaGenerator();
var myType = typeof(MyClass);
var schema = jsonSchemaGenerator.Generate(myType);
schema.Title = myType.Name; // this doesn't seem to get done within the generator

then write it to a file …

var writer = new StringWriter();
var jsonTextWriter = new JsonTextWriter(writer);
schema.WriteTo(jsonTextWriter);
var prettyString = JsonPrettifier.Prettify(writer.ToString());
var fileWriter = new StreamWriter("MySchema.txt");
fileWriter.WriteLine(schema.Title);
fileWriter.WriteLine(new string('-', schema.Title.Length));
fileWriter.WriteLine(prettyString);
fileWrite.Close();

What took me a while to figure out was that MyClass needs to be decorated with specific attributes in order for the schema to be correctly generated.

public class MyClass
{
    [JsonProperty(Required = Required.Always)]
    public string Forename { get; set; }

    [JsonProperty(Required = Required.Always)]
    public string Surname { get; set; }

    [JsonProperty(Required = Required.Always)]
    public string EmailAddress { get; set; }

    [JsonProperty(Required = Required.AllowNull)]
    public string MobilePhoneNumber { get; set; }
}

So, the JsonProperty attribute is your friend here! I took my a while to figure out, including some time stepping through the Json.NET source code in the debugger.

I recently wrote about using reflection to check for null values in conjunction with the TestCase attribute. I’ve just taken this a step further by creating a derived Assert class …

public class Assert : NUnit.Framework.Assert
{
    public static void IsFieldEqual(object obj, string propertyName, object expectedValue)
    {
        var type = obj.GetType();
        var prop = type.GetProperty(propertyName);
        var actualValue = prop.GetValue(obj, null);
        AreEqual(expectedValue, actualValue);
    }
}

This allows me to write tests to check the value of each field in a result object and have the assert fail on the specific field, it also doesn’t stop the other field being tested. So, using the TestCase attribute I can write tests such as this …

[TestCase("Forename", "Antony")]
[TestCase("Surname", "Scott")]
public void example_test(string fieldname, object expectedValue)
{
    // Arrange
    Context.AddPerson(new Person { ID = 1, Forename = "Antony", Surname = "Scott" });

    // Act
    var result = Service.GetPerson(1);

    // Assert
    Assert.IsFieldEqual(result, fieldname, expectedValue);
}

Obviously this is an over-simplified example. But, the idea is that I can now have a complex object being loaded up by an integration test into my database. I then use a Service of some kind (what I’m testing) to query my database and I can then make sure all the correct details have been retrieved from the database.

I recently wrote about how to Automatically Add Framework Config Classes to the Model Builder. Since writing that post I have come across a situation where I was writing the exact same model class in a different application. That just didn’t smell right to me, since the other applications data access layer had been packaged up by nuget I could simply add a reference to it. That’s all well and good, but I didn’t want to have to go to any special effort to add the model configuration classes I needed to my modelbuilder. So, I’ve created a fairly simple (although it’s taken me a while to get it working how I want it) base class from which I can derive my context classes.

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.IO;
using System.Linq;
using System.Reflection;

namespace Base.EntityFramework
{
    public abstract class BaseDbContext : DbContext
    {
        protected BaseDbContext() { }
        protected BaseDbContext(string connectionString) : base(connectionString) { }

        private IEnumerable<Type> GetTypes()
        {
            var type = typeof(EntityTypeConfiguration<>);
            return GetType()
                .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                .Where(p => p.PropertyType.IsGenericType &&
                            p.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>))
                .Select(p => type.MakeGenericType(p.PropertyType.GetGenericArguments().First()))
                .ToArray();
        }

        private static void LoadAllEntityConfigurationsFromAllAssemblies(DbModelBuilder modelBuilder, IEnumerable<Type> types, string assemblyFilter, IEnumerable<string> namePartFilters)
        {
            var path = Path.GetDirectoryName((new Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath);
            new DirectoryCatalog(path, assemblyFilter)
                .LoadedFiles
                .Where(x =>
                {
                    var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(x.ToLower());
                    if (fileNameWithoutExtension != null)
                    {
                        var parts = fileNameWithoutExtension.Split(".".ToCharArray());
                        return parts.Any(part => namePartFilters.Any(namePartFilter => part == namePartFilter.ToLower()));
                    }
                    return false;
                })
                .Select(Assembly.LoadFrom)
                .ToList()
                .ForEach(assembly => assembly.GetTypes()
                                         .Where(t => types.Contains(t.BaseType))
                                         .Select(Activator.CreateInstance)
                                         .ToList<dynamic>()
                                         .ForEach(instance => modelBuilder.Configurations.Add(instance)));
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            var typesToLoad = GetTypes();
            LoadAllEntityConfigurationsFromAllAssemblies(modelBuilder, typesToLoad, "*.dll", new[] { "Data", "Domain" });
        }

    }
}

and in english ….

  1. Discover which classes for which I need to find and load the relevant EntityTypeConfiguration<> class. This is done with a little bit of reflection in the GetTypes() method.
  2. Use MEF to find the assemblies the config classes might be in. In this case it’s all of them (*.dll), but that could be changed to whatever is best for your situation.
  3. Use the namePartFilters to narrow down the list of assemblies further. In this case I’m looking for anything with “Data” or “Domain” in the filename (after it’s been split by periods).
  4. Load each assembly.
  5. Load any generic EntityTypeConfiguration types for the model classes used within my context class (the one which is derived from this base class).
  6. Instantiate each config class.
  7. Add it to the modelBuilder’s configurations.

Since this is a base class I can get this behaviour whenever I derive from it ….

    public class DomainContext : BaseDbContext, IDomainContext
    {
        public IDbSet<Employee> Employees { get; set; }

        public DomainContext() { }
        public DomainContext(string connectionString) : base(connectionString) { }

        IQueryable<Employee> IDomainContext.Employees { get { return Employees; } }
    }

What this allows me to do is use models from any assembly I am referencing in my application and just add it to my Context. Any configuration class for it will then be automatically added to the model builder.

I’ve just completed a bit of TDD. Proper TDD, I wrote the code to pass the tests and wrote the tests first. Anyway, one thing I needed control over was the concept of “now”. This particular method I was testing/writing deals with DateTime objects.

I needed a way of defining, on a per test basis, what “now” is. There were two steps to achieving this. Firstly, I needed to use an interface to get “now”.

    public interface IDateTimeProvider
    {
        DateTime Now { get; }
    }

So, rather than using DateTime.Now, I use DateTimeProvider.Now.

The second step is creating the mock IDateTimeProvider and using the lazy loading feature of Moq. In this particular case I am using Moq and a test base class …

    [TestFixture]
    public abstract class BaseTest
    {
        private Mock<IDateTimeProvider> _mockDateTimeProvider;
        protected IDateTimeProvider DateTimeProvider { get { return _mockDateTimeProvider.Object; } }

        [SetUp]
        public void Setup()
        {
            _mockDateTimeProvider = new Mock<IDateTimeProvider>();
            Now = DateTime.MinValue;
            _mockDateTimeProvider.Setup(x => x.Now).Returns(() =>
                                                               {
                                                                   if (Now == DateTime.MinValue)
                                                                   {
                                                                       throw new Exception("'Now' property must be set in each [Test] method");
                                                                   }
                                                                   return Now;
                                                               });
        }

        protected DateTime Now { private get; set; }
    }

So, I have a DateTime property, which is evaluated whenever the IDateTimeProvider.Now method is called. I added a little check to make sure the Now property is set in each test. That, coupled with setting Now to DateTime.MinValue means any test which doesn’t set the value will get a helpful message in your chosen test runner.

The crucial part of that code and what makes it really useful is the lazy evaluation, which is done like so …

                                                            () =>
                                                               {
                                                                   if (Now == DateTime.MinValue)
                                                                   {
                                                                       throw new Exception("'Now' property must be set in each [Test] method");
                                                                   }
                                                                   return Now;
                                                               }

I’ve also made the Now and _mockDateTimeProvider private so they cannot be used, forcing the use of the DateTimeProvider.

Here is an example test …

        [Test]
        public void ExampleTest()
        {
            Now = DateTime.Parse("30 Nov 2011 15:00");

            // Arrange

            // Act
            var result = DateTimeProvider.Now;

            // Assert
            Assert.That(result, Is.EqualTo(DateTime.Parse("30 Nov 2011 15:00")));
        }

I’ve explicitly defined the dates in my asserts so it’s a little more obvious what is going on. I’ve also used DateTime.Parse as it’s easier to read. I’ve put the assignment of the Now property before the Arrange section as it’s really a pre-arrange step.

It’s not totally necessary to require Now to be configured explicitly for each test, but I think it makes things a little easier to read for developers coming to this code fresh. It would be possible to have a default value for “Now” but that isn’t very discoverable.