Модульное тестирование метода клонирования с Moq в C # - PullRequest
2 голосов
/ 18 апреля 2009

У меня есть несколько базовых классов с методами клонирования:

public class SimpleClass
{
    public int ValueA { get; set; }

    public string ValueB { get; set; }

    public ulong ValueC { get; set; }

    public SimpleClass TypedClone()
    {
        var item = new SimpleClass
        {
            ValueA = this.ValueA,
            ValueB = this.ValueB,
            ValueC = this.ValueC 
        };

        return item;
    }
}

Мне нужен модульный тест, который сообщит мне, если я добавлю ValueD, но забуду добавить его в метод Clone. Моей первой попыткой было использование Moq и его метода VerifyGet, чтобы убедиться, что к каждому свойству обращались.

    public void GenericCloneTest()
    {
        var mock = new Mock<SimpleClass>();
        var c = mock.Object.GenericClone();
        var properties = typeof(SimpleClass).GetProperties();

        foreach (var property in properties)
        {
            var expression = Expression.Property(
                Expression.Parameter(typeof(SimpleClass), "c"), 
                property);

            var type = Expression.GetFuncType(typeof (SimpleClass),  
                property.PropertyType);

            var actionExpression = Expression.Lambda(type, expression,
                Expression.Parameter(typeof(SimpleClass), "c"));

            mock.VerifyGet<object>
                ((Expression<Func<SimpleClass,object>>)actionExpression);
        }
    }

Это не работает, потому что метод VerifyGet должен знать тип возвращаемого метода доступа к свойству, и я не могу найти какой-либо способ вставить его во время выполнения (вы заметите мою неудачную попытку использовать "объект") который разбился и сгорел).

Я даже не уверен, что использование Moq - хорошая идея, это была только моя первая.

ОБНОВЛЕНИЕ: не имея быстрого и простого универсального способа тестирования метода клонирования, я остановился на написании специфических для каждого типа тестов. Это все еще оставляет меня с проблемой знания, когда свойства были добавлены. Я решил добавить это в мои тесты клонов:

      var signature = typeof (Connection)
            .GetProperties()
            .Select(p => p.Name)
            .Aggregate(
                new StringBuilder(), 
                (builder, name) =>
                    builder.Append(name)).ToString();

      Assert.AreEqual(
           "DataSessionStateDataTechnologyBytesReceivedBytesSentDuration",
           signature);

Если я добавлю свойство, тест не пройден. От меня по-прежнему зависит, насколько я ответственен, чтобы исправить оставшуюся часть теста, когда совпадение сигнатур окажется неудачным.

Ответы [ 2 ]

2 голосов
/ 18 апреля 2009

Вы действительно не хотите использовать Moq здесь, вам просто нужно использовать отражение. По сути, напишите тест, который создает экземпляр вашего объекта, устанавливает каждое свойство, клонирует его, а затем проверяет, что каждое свойство равно клону.

Как сказал Пол, посмотрите на MemberwiseClone (), который в основном делает это за вас, или, по крайней мере, внедрите ICloneable, который является стандартной практикой для этого. (MemberwiseClone () делает только поверхностную копию, поэтому вам может потребоваться реализовать ICloneable). Тогда вы даже можете написать тест, который просматривает вашу сборку для всего, что реализует ICloneable, и тестирует его.

1 голос
/ 18 апреля 2009

Один из самых простых способов обеспечить получение всех ваших полей - просто использовать метод MemberwiseClone (). Это автоматически скопирует все ваши поля классов в новый экземпляр.

...