Предотвращение вылова NUnit AssertionException? - PullRequest
1 голос
/ 15 сентября 2010

Сейчас я работаю над проектом, в котором мне нужно взаимодействовать с кодом, который проглатывает исключения. В частности, я пишу модульные тесты NUnit. В некоторых местах я хочу встроить утверждения в код, который передается как делегат, как часть насмешки над определенным поведением. У меня проблема в том, что AssertionException проглатывается кодом, вызывающим делегат, что означает, что тест пройден, даже если тест Assert не выполнен.

Есть ли способ сообщить NUnit о том, что должен произойти сбой теста, который нельзя обойти, перехватив AssertionException? Я не могу изменить код, который поглощает исключения, поскольку у меня нет полной собственности, и он уже находится в полупроизводственном использовании. Я надеюсь, что есть чистый способ сделать это.

Лучшее, что я придумал, примерно так:

    private static string _assertionFailure;
    public static void AssertWrapper(Action action)
    {
        try
        {
            action();
        }
        catch (AssertionException ex)
        {
            _assertionFailure = ex.Message;
            throw;
        }
    }

    [Test]
    [ExpectedException(typeof(AssertionException))]
    public void TestDefeatSwallowing()
    {
        Action failure = () => AssertWrapper(() => Assert.Fail("This is a failure"));

        EvilSwallowingMethod(failure);

        if (_assertionFailure != null)
            Assert.Fail(_assertionFailure);
    }

    private void EvilSwallowingMethod(Action action)
    {
        try
        {
            action();
        }
        catch
        {
        }
    }

Это работает, но довольно уродливо. Я должен обернуть каждый вызов Assert и в конце каждого теста должен проверить, было ли утверждение проглочено.

1 Ответ

2 голосов
/ 15 сентября 2010

Так вы делаете что-то подобное? (это использует синтаксис Moq)

var dependency1 = new Mock<IDependency1>();
dependency1.Setup(d => d.CalledMethod([Args])
    .Callback(TestOutArgsAndPossiblyThrow);

var objectUnderTest = new TestedObject(dependency1.Object);
objectUnderTest.MethodThatCallsIDependency1dotCalledMethod();

А у вас TestOutArgsAndPossiblyThrow инкапсулировано в вашем AssertWrapper классе?

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

Я все еще говорю, что вам будет гораздо лучше с соответствующей регистрацией и уведомлением (вам не обязательно уведомлять конечных пользователей, обязательно). К слову @ TrueWill - что делает вы делаете, когда есть IOException или база данных недоступна?

РЕДАКТИРОВАТЬ ОБСУЖДЕНИЕ

Ваш сценарий структурирован так?

TEST -> TESTED CODE -> SWALLOWING CODE -> THROWING MOCK
...