Тестирование аннотация SettingConverter с глумится


Один из моих рамок использует ISettingConverter интерфейс как абстракцию для сериализации.

public interface ISettingConverter
{
    [NotNull]
    object Deserialize([NotNull] object value, [NotNull] Type targetType);

    [NotNull]
    object Serialize([NotNull] object value);
}

Она реализуется реферат SettingConverter класс, который содержит логику, которая предотвращает ненужные звонки для фактических реализаций и что может переход на аварийный режим к умолчанию тип объекта для сериализации (первый тип по списку), если цель не поддерживает тип значения изначально. Цель может быть база данных или приложение.config или реестре Windows (которая изначально поддерживает более типов, то просто строки).

public abstract class SettingConverter : ISettingConverter
{
    private readonly ISet<Type> _supportedTypes;

    private readonly Type _fallbackType;

    protected SettingConverter(IEnumerable<Type> supportedTypes)
    {
        _supportedTypes = new HashSet<Type>(supportedTypes ?? throw new ArgumentNullException(nameof(supportedTypes)));
        _fallbackType = supportedTypes.FirstOrDefault() ?? throw new ArgumentException("There must be at least one supprted type.");
    }

    public object Deserialize(object value, Type targetType)
    {
        return
            value.GetType() == targetType 
                ? value 
                : DeserializeCore(value, targetType);
    }

    [NotNull]
    protected abstract object DeserializeCore([NotNull]object value, [NotNull] Type targetType);

    public object Serialize(object value)
    {
        var targetType =
            _supportedTypes.Contains(value.GetType())
                ? value.GetType()
                : _fallbackType;

        return
            value.GetType() == targetType
                ? value
                : SerializeCore(value, targetType);
    }

    [NotNull]
    protected abstract object SerializeCore([NotNull]object value, [NotNull] Type targetType);
}

Чтобы проверить это базовый класс, я написал несколько тестов с помощью бесплатной версии JustMock рамки и действия MSTest двигателя с помощью Visual студии 2017.


Первый тест гарантирует, что DeserializeCore не вызывается, если тип значения уже не имеет целевого типа.

    [TestMethod]
    public void Deserialize_ValueHasTargetType_DeserializeCoreNotCalled()
    {
        var settingConverter = Mock.Create<SettingConverter>(Behavior.CallOriginal, (IEnumerable<Type>)new[] { typeof(string) });

        Mock
            .NonPublic
            .Arrange<object>(
                settingConverter, 
                "DeserializeCore", 
                ArgExpr.IsAny<object>(), 
                ArgExpr.IsAny<Type>())
            .OccursNever();

        var result = settingConverter.Deserialize("foo", typeof(string));

        settingConverter.Assert();
        Assert.AreEqual("foo", result);
    }

Тогда у меня есть тест, чтобы убедиться в обратном, это, DeserializeCore должен быть вызван, если тип значения не является одним из видов цели. В этом случае int != string.

    [TestMethod]
    public void Deserialize_ValueHasOtherType_DeserializeCoreCalled()
    {
        var settingConverter = Mock.Create<SettingConverter>(Behavior.CallOriginal, (IEnumerable<Type>)new[] { typeof(string) });

        Mock
            .NonPublic
            .Arrange<object>(
                settingConverter, 
                "DeserializeCore", 
                ArgExpr.IsAny<object>(), 
                ArgExpr.IsAny<Type>())
            .OccursOnce();

        settingConverter.Deserialize("foo", typeof(int));

        settingConverter.Assert();
    }

Другие два теста убедитесь в том, что сериализация делает то, что предполагается. Итак, первый тест проверяет, что SerializeCore не позвонила, потому что тип значения уе-это же как один из видов, что объект поддерживает.

    [TestMethod]
    public void Serialize_ValueHasSupportedType_SerializeCoreNotCalled()
    {
        var settingConverter = Mock.Create<SettingConverter>(Behavior.CallOriginal, (IEnumerable<Type>)new[] { typeof(string) });

        Mock
            .NonPublic
            .Arrange<object>(
                settingConverter,
                "SerializeCore",
                ArgExpr.IsAny<object>(),
                ArgExpr.IsAny<Type>())
            .OccursNever();

        settingConverter.Serialize("foo");

        settingConverter.Assert();
    }

Последние анализы проверяет SerializeCore вызывается резервный тип, который в данном случае является string потому что int не поддерживается и должны быть преобразованы в первую очередь.

    [TestMethod]
    public void Serialize_ValueHasUnsupportedType_SerializeCoreCalledWithFallbackType()
    {
        var settingConverter = Mock.Create<SettingConverter>(Behavior.CallOriginal, (IEnumerable<Type>)new[] { typeof(string) });

        Mock
            .NonPublic
            .Arrange<object>(
                settingConverter,
                "SerializeCore",
                ArgExpr.IsAny<object>(),
                ArgExpr.Matches<Type>(t => t == typeof(string)))
            .OccursOnce();

        settingConverter.Serialize(123);

        settingConverter.Assert();
    }

Я хотел бы взглянуть на эти тесты и расскажи, как хорошо или плохо они и что бы вы улучшили в случае чего? Их назначение и осуществление ясно? Я выбрал правильные имена для всего?



86
2
задан 26 января 2018 в 08:01 Источник Поделиться
Комментарии