Модульное тестирование с entlib - исключая уловы - PullRequest
2 голосов
/ 14 августа 2010

У меня есть метод, который выполняет некоторые операции ввода-вывода, которые обычно выглядят так:

public bool Foo()
{
    try
    {
        // bar

        return true;
    }
    catch (FileNotFoundException)
    {
        // recover and complete
    }
    catch (OtherRecoverableException)
    {
        // recover and complete
    }
    catch (NonRecoverableException ex)
    {
        ExceptionPolicy.HandleException(ex, "LogException");
        return false;
    }
}

Этот метод не является критически важным для выполнения, есть внешние шаги восстановления - и это довольно распространенное явление для исключения NonRecoverableException - в спецификации он возвращает false, отчет «не может быть завершен в настоящее время» и обработка движется вперед. NonRecoverableException не переводит программу в недопустимое состояние.

Когда я выполняю модульное тестирование и выдается одно из этих исключений, я получаю сообщение об ошибке

Activation error occured while trying to get instance of type ExceptionPolicyImpl

И я хотел бы исключить это в пользу получения фактической / исходной информации об исключении вместо того, чтобы EntLib не мог вести журнал (и, действительно, вызывать исключение NonRecoverableException и иметь блок [ExpectedException (typeof (NonRecoverableException))]]] тест, чтобы убедиться, что этот метод соответствует спецификации.

Как я могу это сделать?

редактировать Использование директив препроцессора не идеально, так как я ненавижу видеть специфичный для теста код в кодовой базе.

Ответы [ 2 ]

10 голосов
/ 17 августа 2010

Тестируемость вашего кода с использованием статических фасадов Entlib сложна.Немного не изменяя свой код, ваш единственный ответ - добавить файл app.config в тестовую сборку и настроить блок исключений Entlib с безобидной политикой, которая ничего не делает.

Однако в Entlib 4 (и5, который я вижу, вы используете) есть другой способ.Мы добавили точку входа экземпляра во все блоки специально для улучшения истории тестируемости.Для блока исключений этот экземпляр - ExceptionManager.Используя это довольно просто.Получите экземпляр диспетчера исключений в свой тип, а затем вызовите его вместо ExceptionPolicy.Примерно так:

public class Whatever {
    private ExceptionManager exm;

    public Whatever(ExceptionManager exm) { this.exm = exm; }

    public bool Foo() {
        try {
            ... do whatever ...
        }
        catch(NonRecoverableException ex) {
            exm.HandleException(ex, "LogException");
            return false;
        }
    }
}

Теперь, когда у вас это есть, вы можете смоделировать ExceptionManager (это абстрактный базовый класс), чтобы практически не открывать его во время теста, либо вручную, либо с помощьюфреймворк фиктивных объектов.

Если вы не хотите заставлять своих пользователей использовать контейнер DI, вы можете добавить конструктор по умолчанию, который получает текущий менеджер исключений:

public class Whatever {
    private ExceptionManager exm;

    public Whatever() : this(EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>()) { }        
    public Whatever(ExceptionManager exm) { this.exm = exm; }
}

Конечные пользователииспользуйте конструктор по умолчанию, ваши тесты используют тот, который принимает явный ExceptionManager, и у вас есть ловушка для макетирования всего, что использует Entlib.

Все блоки теперь имеют эти классы "Manager" (где они имеют смыслво всяком случае).

1 голос
/ 14 августа 2010

Хм, вы могли бы реорганизовать код, чтобы поместить все в блок try в отдельный метод и настроить ваши тесты для вызова этого вместо существующего метода?

...