Помогите мне понять, что происходит с этой ошибкой в ​​моем модульном тесте - PullRequest
2 голосов
/ 09 ноября 2010

У меня есть метод, который сериализует коллекцию в файл, используя XmlSerializer.

    public void Save(List<RetryAttempt> retryAttempts)
    {
        FileStream fs = new FileStream(this.fileName, FileMode.Create);

        try
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<RetryAttempt>));
            xmlSerializer.Serialize(fs, retryAttempts);
        }
        catch (Exception ex)
        {
            LocalLogger.LogError("Unable to save retry information to xml file.", ex.ToString());
        }
        finally
        {
            fs.Close();
        }
    }

Затем у меня есть другой метод, который десериализует коллекцию обратно из файла

    public List<RetryAttempt> GetRetryAttempts()
    {
        List<RetryAttempt> retryAttempts = new List<RetryAttempt>();

        if (File.Exists(this.fileName))
        {
            FileStream fs = new FileStream(this.fileName, FileMode.Open);

            try
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<RetryAttempt>));
                retryAttempts = (List<RetryAttempt>)xmlSerializer.Deserialize(fs);
            }
            catch (Exception ex)
            {
                LocalLogger.LogError("Unable to read from retry xml file.", ex.ToString());
            }
            finally
            {
                fs.Close();
            }
        }

        return retryAttempts;
    }

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

    [Test]
    public void GetRetryAttempts_AttemptsExist_ListOfAttemptsReturned()
    {
        this.attempt = new RetryAttempt("1234", 4);
        this.attempts = new List<RetryAttempt>() { attempt };
        this.xmlStore = new XmlRetryFileStore(RetryType.Download);
        xmlStore.Save(attempts);

        List<RetryAttempt> savedAttempts = xmlStore.GetRetryAttempts();
        Assert.Contains(attempt, savedAttempts);
    }

Я бы ожидал, что список моего пользовательского объекта будет содержать «попытку», которую я сериализовал в файл. Вместо этого я получаю следующий сбой.

Ожидается: коллекция, содержащая Но было:

Это сообщение, по-видимому, предполагает, что вместо возвращаемой коллекции был возвращен только один объект. Это, очевидно, не тот случай - есть возвращаемый List, который содержит только один элемент - я вижу коллекцию в ближайшем окне, и все выглядит хорошо. Я могу запустить тест с отладчиком, и все, кажется, в порядке. Если я просто создаю коллекцию и утверждаю, что она содержит элемент, не сохраняя и не получая его из XML, тогда он работает нормально, поэтому точка сбоя должна быть вокруг сериализации?

Ответы [ 3 ]

3 голосов
/ 09 ноября 2010

Я подозреваю, что ваш класс не реализует собственную переопределенную версию метода .Equals. В противном случае метод содержит проверку ссылок, и поскольку вы сравниваете сериализованные версии с оригинальными, экземпляры не совпадают.

Я бы предложил реализовать это (наряду с GetHashCode, чтобы вы могли делать сравнения на равенство

1 голос
/ 09 ноября 2010

Вместо того, чтобы эти методы записывали в файл, я бы порекомендовал вам изменить их подпись для работы с TextWriter.Таким образом, они более независимы от основного хранилища:

public void Save(List<RetryAttempt> retryAttempts, TextWriter writer)
{
    try
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<RetryAttempt>));
        xmlSerializer.Serialize(writer, retryAttempts);
    }
    catch (Exception ex)
    {
        LocalLogger.LogError("Unable to save retry information to xml file.", ex.ToString());
    }
}

Теперь ваш тест может стать:

[TestMethod]
public void TestSerialize()
{
    // arrange
    var sb = new StringBuilder();
    using (var writer = new StringWriter(sb))
    {
        this.attempt = new RetryAttempt("1234", 4);
        this.attempts = new List<RetryAttempt>() { attempt };
        this.xmlStore = new XmlRetryFileStore(RetryType.Download);
        this.xmlStore.Save(writer, this.attempts);
    }

    string actual = sb.ToString();
    // TODO: assert on the resulting XML
}

Также обратите внимание, что вы не должны использовать метод GetRetryAttempts для подтвержденияв модульном тестировании метода Save.Эти два метода должны быть отдельными и иметь свои отдельные тесты.

И метод GetRetryAttempts:

public List<RetryAttempt> GetRetryAttempts(TextReader reader)
{
    try
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<RetryAttempt>));
        return (List<RetryAttempt>)xmlSerializer.Deserialize(reader);
    }
    catch (Exception ex)
    {
        LocalLogger.LogError("Unable to read from retry xml file.", ex.ToString());
    }
    return new List<RetryAttempt>();
}
1 голос
/ 09 ноября 2010

Я полагаю, что вы можете столкнуться с тем, как сравниваются объекты - в .Net равенство объектов обрабатывается путем сравнения того, указывают ли переменные в вопросе на один и тот же объект в памяти.

в этом случае десериализация создает новый экземпляр вашего списка с новым RetryAttempt. Новый RetryAttempt может содержать те же значения, что и сериализованный вами (это должно быть), но у него будет другой адрес памяти.

Попробуйте протестировать определенное свойство на RetryAttempt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...