NUnit - Как протестировать все классы, которые реализуют определенный интерфейс

Эта проблема может возникнуть при использовании метода ASP.NET MVC RedirectToAction. Чтобы предотвратить отображение формы в div, вы можете просто сделать какой-то фильтр ответа ajax для входящих ответов с $ .ajaxSetup. Если ответ содержит перенаправление MVC, вы можете оценить это выражение на стороне JS. Пример кода для JS ниже:

$.ajaxSetup({
    dataFilter: function (data, type) {
        if (data && typeof data == "string") {
            if (data.indexOf('window.location') > -1) {
                eval(data);
            }
        }
        return data;
    }
});

Если данные: "window.location = '/ Acount / Login'" выше фильтр поймает это и оценит, чтобы сделать перенаправление вместо того, чтобы отображать данные.

30
задан Frep D-Oronge 2 September 2008 в 08:13
поделиться

7 ответов

Если у Вас есть реализация классов какой-либо интерфейс тогда, они все должны реализовать методы в том интерфейсе. Для тестирования этих классов, необходимо создать класс модульного теста для каждого из классов.

Отпускает с более умным маршрутом вместо этого; если Ваша цель к [1 120], избегают кода и дублирования тестового кода , Вы могли бы хотеть создать абстрактный класс вместо этого, который обрабатывает возвращение код.

, Например, у Вас есть следующий интерфейс:

public interface IFoo {

    public void CommonCode();

    public void SpecificCode();

}

Вы могли бы хотеть создать абстрактный класс:

public abstract class AbstractFoo : IFoo {

    public void CommonCode() {
          SpecificCode();
    }

    public abstract void SpecificCode();

}

Тестирование, которое легко; реализуйте абстрактный класс в тестовом классе любой как внутренний класс:

[TestFixture]
public void TestClass {

    private class TestFoo : AbstractFoo {
        boolean hasCalledSpecificCode = false;
        public void SpecificCode() {
            hasCalledSpecificCode = true;
        }
    }

    [Test]
    public void testCommonCallsSpecificCode() {
        TestFoo fooFighter = new TestFoo();
        fooFighter.CommonCode();
        Assert.That(fooFighter.hasCalledSpecificCode, Is.True());
    }
}

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

[TestFixture]
public void TestClass : AbstractFoo {

    boolean hasCalledSpecificCode;
    public void specificCode() {
        hasCalledSpecificCode = true;
    }

    [Test]
    public void testCommonCallsSpecificCode() {
        AbstractFoo fooFighter = this;
        hasCalledSpecificCode = false;
        fooFighter.CommonCode();
        Assert.That(fooFighter.hasCalledSpecificCode, Is.True());
    }        

}

Наличие абстрактного класса заботится об общем коде, который подразумевает интерфейс, дает намного более чистый дизайн кода.

я надеюсь, что это имеет смысл Вам.

<час>

Как примечание стороны, это - шаблон общего умысла, названный Шаблонный шаблон Метода . В вышеупомянутом примере шаблонный метод CommonCode, метод и SpecificCode называют тупиком или рычагом. Идея состоит в том, что любой может расширить поведение без потребности знать негласно материал.

Много платформ полагается на эту поведенческую модель, например, ASP.NET , где необходимо реализовать рычаги на странице или пользовательские элементы управления такой как сгенерированный Page_Load метод, который называют Load событие, шаблонные вызовы метода рычаги негласно. Существует намного больше примеров этого. В основном что-либо, что необходимо реализовать, который использует слова "загрузка", "init", или "рендеринг", называет шаблонный метод.

13
ответ дан 5 revs, 3 users 96% 2 September 2008 в 08:13
поделиться

Я не думаю, что это - лучшая практика.

простая истина - то, что интерфейс является не чем иным как контрактом, что метод реализован. Это не контракт на также a.), как метод должен быть реализован и b.), что тот метод должен делать точно (он только гарантирует тип возврата), двумя причинами, что я подбираю, был бы Ваш повод в желании этого вида теста.

, Если Вы действительно хотите управлять своей реализацией метода, у Вас есть опция:

  • Реализация его как метод в абстрактном классе, и наследовались этому. Необходимо будет все еще наследовать его в реальный класс, но Вы уверены что, если это явно не переопределяется, что метод сделает ту корректную вещь.
  • В.NET 3.5/C# 3.0, реализовывая метод как дополнительную ссылку метода против Интерфейса

Пример:

public static ReturnType MethodName (this IMyinterface myImplementation, SomeObject someParameter)
{
    //method body goes here
}

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

3
ответ дан Jon Limjap 2 September 2008 в 08:13
поделиться
  • 1
    Добавление этого зафиксировало его для меня. 😊 – Jeff 31 March 2017 в 02:09

Как насчет иерархии классов [TestFixture] s? Поместите общий тестовый код в основной тестовый класс и наследуйте его в дочерние тестовые классы..

1
ответ дан Andrei Rînea 2 September 2008 в 08:13
поделиться
  • 1
    Это должно быть добавлено наряду с @David ответом Транга. – Augustine P A 8 November 2017 в 14:15

Я не соглашаюсь с Jon Limjap , когда он говорит,

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

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

public interface List {

  // adds o and returns the list
  public List add(Object o);

  // removed the first occurrence of o and returns the list
  public List remove(Object o);

}

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

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

, Если Вы не хотите издержки контрактов, я рекомендую тестовые буровые установки, вроде того, что рекомендовал Spoike:

abstract class BaseListTest {

  abstract public List newListInstance();

  public void testAddToList() {
    // do some adding tests
  }

  public void testRemoveFromList() {
    // do some removing tests
  }

}

class ArrayListTest < BaseListTest {
  List newListInstance() { new ArrayList(); }

  public void arrayListSpecificTest1() {
    // test something about ArrayLists beyond the List requirements
  }
}
11
ответ дан Community 2 September 2008 в 08:13
поделиться
  • 1
    Только необходимый первая строка searchController.hidesNavigationBarDuringPresentation = false (быстро) – hashier 7 June 2016 в 13:48

@Emperor XLII

мне нравится звук комбинаторных тестов в MbUnit, я попробовал метод испытания интерфейса абстрактного базового класса NUnit, и хотя это действительно работает, у Вас должно было бы быть отдельное тестовое приспособление для каждого интерфейса, который реализует класс (так как в C# нет никакого множественного наследования - хотя внутренние классы могут использоваться, который довольно прохладен). В действительности это прекрасно, возможно, даже выгодное, потому что это группирует Ваши тесты для класса с реализацией интерфейсом. Но было бы хорошо, если платформа могла бы быть более умной. Если я мог бы использовать атрибут для маркировки класса как 'официальный' тестовый класс для интерфейса, и платформа будет искать блок под тестом для всех классов, которые реализуют интерфейс и запускают те тесты на нем.

, Который был бы прохладен.

1
ответ дан Frep D-Oronge 2 September 2008 в 08:13
поделиться
  • 1
    Я зафиксировал мой, просто реализовав методы делегата – jaytrixz 21 July 2016 в 07:11

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

  • Для xUnit.net , я создал библиотека Type Resolver для поиска всех реализаций конкретного типа (расширения xUnit.net являются просто тонкой оберткой по функциональности Преобразователя Типа, таким образом, это может быть адаптировано к использованию в других платформах).
  • В MbUnit, можно использовать CombinatorialTest с UsingImplementations атрибуты на параметрах.
  • Для других платформ, шаблон базового класса упомянутый Spoike может быть полезным.

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

1
ответ дан Community 2 September 2008 в 08:13
поделиться

Я не использую NUnit, но я протестировал интерфейсы C++. Я сначала протестировал бы класс TestFoo, который является базовым внедрением его для проверки универсальных работ материала. Тогда просто необходимо протестировать материал, который уникален для каждого интерфейса.

0
ответ дан graham.reeds 2 September 2008 в 08:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: