Попытка предоставить дополнительную информацию при использовании xUnit Assert.Throws

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

Я тестирую свой MVC Controllers и хочу убедиться, что все они предоставляют ArgumentNullException, если они построены с передачей null в качестве аргументов (в реальном мире они разрешаются через Castle).

Итак, у меня есть личное поле в классе Test:

private IEnumerable<Type> ControllerTypes = typeof(MyBaseController).Assembly.GetTypes().Where(t => IsController(t));

Затем мой метод тестирования:

    [Fact]
    public void EnsureControllersThrowIfProvidedWithNull() {
        foreach (var controller in ControllerTypes) {
            var ctrs = GetConstructorsForType(controller);
            if (null == ctrs || !ctrs.Any()) { //if the controller has no constructors, that's fine, we just skip over it
                continue;
            }
            var ctr = ctrs.ElementAt(0);
            var ctrParamsAsNull = ctr.GetParameters().Select(p => (object)null);
            Assert.Throws<ArgumentNullException>(() => {
                ctr.Invoke(ctrParamsAsNull.ToArray());
            });
        }
    }

Итак, все работает нормально, я запускаю средство запуска тестов, и один из моих Controllers не выдает ArgumentNullException при передаче null, отлично, мой тест не выполняется, но я не знаю, какой это был контроллер, из данного вывода.

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

Или я здесь просто неправильно использую модульный тест?

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

Спасибо

Примечание. В логике теста есть изъян, что означает, что он не полностью покрывает то, что я ожидал, пока он выдает ArgumentNullException хотя бы для одного аргумента, тогда он пройдет испытание, что неверно. Однако, поскольку аргументы являются интерфейсами, я не могу создать их новый экземпляр. Так что любой, кто хочет скопировать код для теста, я бы не стал этого делать. Не ищу здесь решения этой проблемы.


person Psytronic    schedule 10.05.2013    source источник


Ответы (1)


Assert.Throws - это только вспомогательный метод, который выполняет делегат внутри блока try catch. Вам не обязательно его использовать, и вы можете заменить его собственной реализацией. Что-то вроде:

[Fact]
public void EnsureControllersThrowIfProvidedWithNull() {
    foreach (var controller in ControllerTypes) {
        var ctrs = GetConstructorsForType(controller);
        if (null == ctrs || !ctrs.Any()) { //if the controller has no constructors, that's fine, we just skip over it
            continue;
        }
        var ctr = ctrs.ElementAt(0);
        var ctrParamsAsNull = ctr.GetParameters().Select(p => (object)null);
        book ok = false;
        try
        {
            ctr.Invoke(ctrParamsAsNull.ToArray());
        }
       catch(ArgumentNullException)
       {
            //you get exception you expected so continue
            ok = true;
       }
       if(!ok)
       {
          // you didn't get exception so throw your own exception with message that contains controller type name 
           throw new Exception(String.Format("Ctor on type {0} did not throw ArgumentNullException",controller.Name);
       }
    }
}

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

person Jurica Smircic    schedule 12.05.2013