Кто-нибудь видел библиотеку, которая тестирует WCF DataContracts? Мотивация, стоящая за этим вопросом, заключается в том, что я только что обнаружил ошибку в своем приложении, которая возникла из-за того, что я не аннотировал свойство с помощью атрибута DataMember - в результате это свойство не было сериализовано.

Я имею в виду API, который, учитывая конкретный тип DataContract, автоматически заполняет свои члены случайными данными, включая любые дочерние DataContracts, затем сериализует их с помощью одного из сериализаторов / форматеров WCF, а затем проверяет, что все данные был перенесен.

Кто угодно?

13
Samuel Jack 9 Июн 2009 в 19:33

2 ответа

Лучший ответ

Достаточно просто использовать DataContractSerializer для сериализации вашего объекта в MemoryStream, а затем десериализовать его обратно в существование в качестве нового экземпляра.

Вот класс, демонстрирующий эту сериализацию туда и обратно:

public static class WcfTestHelper
{
    /// <summary>
    /// Uses a <see cref="DataContractSerializer"/> to serialise the object into
    /// memory, then deserialise it again and return the result.  This is useful
    /// in tests to validate that your object is serialisable, and that it
    /// serialises correctly.
    /// </summary>
    public static T DataContractSerializationRoundTrip<T>(T obj)
    {
        return DataContractSerializationRoundTrip(obj, null);
    }

    /// <summary>
    /// Uses a <see cref="DataContractSerializer"/> to serialise the object into
    /// memory, then deserialise it again and return the result.  This is useful
    /// in tests to validate that your object is serialisable, and that it
    /// serialises correctly.
    /// </summary>
    public static T DataContractSerializationRoundTrip<T>(T obj, 
                    IEnumerable<Type> knownTypes)
    {
        var serializer = new DataContractSerializer(obj.GetType(), knownTypes);
        var memoryStream = new MemoryStream();
        serializer.WriteObject(memoryStream, obj);
        memoryStream.Position = 0;
        obj = (T)serializer.ReadObject(memoryStream);
        return obj;
    }
}

Две задачи, за которые вы отвечаете:

  • Заполнение экземпляра в первую очередь разумными данными. Вы можете использовать отражение для установки свойств или предоставить конструктору его аргументы, но я обнаружил, что этот подход не будет работать ни для чего, кроме невероятно простых типов.
  • Сравнение двух экземпляров после деактивации / сериализации в оба конца. Если у вас есть надежная реализация Equals/GetHashCode, возможно, это уже сделано за вас. Опять же, вы можете попробовать использовать общий рефлексивный компаратор, но он может быть не совсем надежным.
11
Drew Noakes 10 Июн 2009 в 10:46
После прохождения теста объекта контракта данных с использованием вышеуказанного метода я попытался использовать реальную реализацию клиент / сервер и все равно получил следующее сообщение: «Входной поток содержит элементы коллекции, которые не могут быть добавлены, если экземпляр имеет значение NULL». Есть идеи, как это проходит через тест?
 – 
slolife
10 Окт 2013 в 00:59
@slolife, вы должны убедиться, что obj, который вы передаете в модульный тест, содержит те же типы элементов в этой коллекции, что и вызывают проблему, которую вы видите. Упоминание null в ошибке предполагает, что ваша коллекция по какой-то причине не инициализируется. Если вы все еще застряли, в качестве нового вопроса с дополнительной информацией (и ссылка на него здесь, если хотите.)
 – 
Drew Noakes
10 Окт 2013 в 13:57
Спасибо за такой ответ! Его можно легко адаптировать для сериализации Json с помощью сериализатора DataContract Json .
 – 
Sebastian
8 Дек 2014 в 13:14

Лучший подход: создать прокси, который сериализует / десериализует все аргументы при вызове метода. Код можно найти здесь: http: //mkramar.blogspot .com / 2013/01 / unit-test-wcf-with-serialization.html.

0
m_kramar 18 Янв 2013 в 08:17