MSTest ThrowsException с условиями для объекта исключения? - PullRequest
0 голосов
/ 14 февраля 2019

Я использую MSTest Assert.ThrowsException, но иногда я хочу добавить условия теста для брошенного объекта исключения, например, проверить, что в сообщении упоминается конкретная фраза, идентификатор, значение данных или что-то еще.

лучшее решение, которое я нашел, это конструкция, которая не использует Assert.ThrowsException, но прибегает к try...catch:

bool success = false;
try
{
    // Code to be tested goes here...
    success = true;
}
catch (Exception e)
{
    Assert.IsInstanceOfType(e, typeof(DesiredExceptionClass));
    // Tests on e go here...
}
if (success)
    Assert.Fail($"Should have thrown {nameof(DesiredExceptionClass)}.");

Есть ли лучший способ?

С "лучше"я имею в виду более читаемый, компактный код, с меньшим количеством «шаблонного».

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

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

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

public static class ExceptionAssert
{
    /// <summary>
    /// Use this method if your UT is using <see cref="ExpectedExceptionAttribute"/> and you want to verify additional expectations
    /// </summary>
    /// <typeparam name="T">The expected exception type base</typeparam>
    /// <param name="action">Execute the unit to test</param>
    /// <param name="verifier">Verify the additional expectations</param>
    public static void AssertException<T>(Action action, Action<T> verifier) where T: Exception
    {
        try
        {
            action();
        }
        catch(T e)
        {
            verifier(e);
            throw;
        }
    }

    /// <summary>
    /// Use this method if your UT is not using <see cref="ExpectedExceptionAttribute"/> and you want to verify additional expectations
    /// </summary>
    /// <typeparam name="T">The expected exception type base</typeparam>
    /// <param name="action">Execute the unit to test</param>
    /// <param name="verifier">Verify the additional expectations</param>
    /// <param name="allowDriven">Indicates if the raised exception can be an instance of driven class</param>
    public static void AssertExceptionWithoutExcepctedExceptionAttribute<T>(Action action, Action<T> verifier, bool allowDriven = true) where T : Exception
    {
        try
        {
            action();
            Assert.Fail("No Exception raised");
        }
        catch (T e)
        {
            if (!allowDriven && e.GetType() != typeof(T))
            {
                Assert.Fail($"The raised exception :: {e.GetType()} is a driven instance of :: {typeof(T)}");
            }
            verifier(e);
        }
    }
}

Теперь вы можете выполнить свой UT как один из следующих:

[TestMethod]
[ExpectedException(typeof(Exception), AllowDerivedTypes = true)] // change the attribute settings
public void Foo()
{
    // do arrange:

    ExceptionAssert.AssertException<Exception>(() => // change "Exception" to the required exception type or left it as any exception
    {
        // do the act:

    }, exception =>
     {
         // do you asserts statements:
     });
}

[TestMethod]
public void FooBar()
{
    // do arrange:

    ExceptionAssert.AssertExceptionWithoutExcepctedExceptionAttribute<Exception>(() => // change "Exception" to the required exception type or left it as any exception
    {
        // do the act:

    }, exception =>
    {
        // do you asserts statements:
    }, false);
}

Кстати, ИМО, вы никогда не должны проверять само исключение, кроме еготип / ведомый (или, если это пользовательское исключение с дополнительной информацией), так как ваш код никогда не должен зависеть от его MSG, стека вызовов и т. д. ... Я думаю, что это причина, по которой MS не добавил к ExpectedExceptionAttribute возможность проверки MSG.

0 голосов
/ 14 февраля 2019

Я использую этот способ:

    Exception exception = null;
        try
        {
            // Code to be tested goes here...
        }
        catch (Exception e)
        {
            exception = e;
        }
        Assert.IsInstanceOfType(exception, typeof(DesiredExceptionClass));
...