Подтвердить что ты не робот

Статические классы UnitTesting

Сценарий. Язык С#, модульное тестирование с использованием VS2008 Единичное тестирование модулей

У меня есть статический класс со статическим конструктором и двумя методами. У меня есть 4 метода тестирования, написанных для тестирования всего класса. У моего Static Constructor есть несколько важных инициализаций.

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

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

4b9b3361

Ответ 1

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

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

Ответ 3

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

public static class MyClass
{
   public static MyClass()
   {
      initialize();
   }

   internal static void initialize()
   {
      // Do initialization (and cleanup if necessary)
   }

   public static void Method1() {}
   public static void Method2() {}
}

Чтобы вызвать внутренние методы, вам нужно использовать атрибут InternalsVisibleTo, как описано в в этом блоге.

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

Но, как сказал Эндрю Шеферд, вы также должны проверить, является ли статический класс лучшим дизайном этого класса.

Ответ 4

Из-за того, что использование комментирования класса только при использовании может привести к немного сложным, но плохо дать ему все равно. Для меня вышесказанное звучит скорее как запах, чем проблема с тестированием.

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

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

Ответ 5

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

Ответ 6

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

Это не бесплатный продукт.

Ответ 7

Похоже, вы пытаетесь проверить статический конструктор. Это кажется плохой идеей.

Рассмотрим извлечение логики инициализации в отдельный (нестатический) класс.

Для обсуждения предположим, что ваш статический класс называется MySingleton, и предположим, что вы создаете новый класс MyInitializer с помощью метода Execute. Статический конструктор MySingleton может создавать экземпляр MyInitializer и вызывать Execute, который выполняет всю инициализацию.

Тогда ваш производственный код может использовать MySingleton и игнорировать MyInitializer. С другой стороны, ваши тесты могут игнорировать MySingleton и весело создавать новый экземпляр MyInitializer для каждого теста, каждый раз получая новое начало.

Ответ 8

Для полноты, если вам нужно reset непубличное поле/переменную статического класса, это также можно сделать с помощью отражения.

using System.Reflection; // or Mono.Reflection

public static class MyClass{
    private static string myString;
}

var newValue = "Potatoes";            
var field = typeof(MyClass).GetField("myString", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, newValue); // the first null is because the class is static, the second is the new value