Как мне выполнить модульный тест для конкретного поведения машины? - PullRequest
2 голосов
/ 15 мая 2009

Я тестирую статический метод, который создает строку URL после проверки прокси-серверов и имен хостов, а также всех видов вещей. Этот метод внутренне опирается на статический флаг System.Net.Sockets.Socket.OSSupportsIPv6. Поскольку это статично, я не могу высмеять эту зависимость.

РЕДАКТИРОВАТЬ: (Это сильно упрощено ... Я не могу изменить структуру метода с флагом, чтобы принять истину / ложь).

На машинах разработки XP рассматриваемый метод возвращает предсказуемый строковый результат (в данном случае http://hostname/....). Наш сервер сборки, который поддерживает IPv6, возвращает совершенно другой результат (он дает мне что-то вроде http://192.168.0.1:80/....).. Пожалуйста, не спрашивайте почему. Дело в том, что есть два разных типа вывода, которые зависят от зависимости операционной системы.

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

Как лучше всего писать тест в этом случае? Должен ли я добавить в свой тест оператор if, который проверяет флаг, а затем ищет два разных результата? Это кажется мне отрывочным, потому что

  1. тест ведет себя иначе в зависимости от среды это запустить в

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

Настроил ли я два теста, по одному для каждой среды, которые просто проходят, если они находятся в неправильной среде? Пишу ли я какое-нибудь сложное регулярное выражение, которое может выделить, какой результат он получил, и использовать больше логики if / else для его проверки?

Любые предложения помогут!

Ответы [ 5 ]

2 голосов
/ 15 мая 2009

Вы можете подделать звонок, введя посредника. Например:

public static class NetworkUtils
{
    private static bool? forcedIPv6Support;

    /// <summary>
    /// Use this instead of Socket.OSSupportsIPv6 to
    /// allow for testing on different operating systems.
    /// </summary>
    public static SupportsIPv6
    {
        get { return forcedIPv6Support ?? Socket.OSSupportsIPv6; }
    }

    /// <summary>Only use in testing!</summary>
    public static void ForceIPv6Support(bool? value)
    {
        forcedIPv6Support = value;
    }
}

Это не совсем приятно, но позволяет вам делать то, что вам нужно.

Ответ ChrisW аналогичен, но с использованием интерфейса. Обычно я был бы поклонником интерфейсного решения, но мне кажется, что это усложняет производственный код и конфигурацию. Мое решение, конечно, менее «чисто», но, возможно, более прагматично. Я позволю тебе судить :) 1008 *

1 голос
/ 15 мая 2009

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

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

, например

public interface IEnvironment
{
    public bool SupportsIPV6 { get; }
}

И тогда ваш статический метод становится.

public static void DoSomething(IEnvironment environment)
{
    if(environment.SupportsIPV6)
    {
        ...
    }
}

Затем предоставьте реализацию IEnvironment, которая вызывает статический метод System.Net, чтобы получить фактические настройки для использования, но фиктивную реализацию для тестирования с известным значением.

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

Е.Г.

public Environment : IEnvironment
{
  private static IEnvironment current = new Environment();
  public static IEnvironment Current
  {
    get { return current; }
    set { current = value; }
  }

  public bool SupportsIPV6
  {
    return System.Net.....
  }
}

Затем вызовите его из статического метода, используя.

public static void DoSomething(IEnvironemnt environment)
{
    if(Environment.Current.SupportsIPV6)
    {
        ...
    }
}

И вы можете изменить его в своих тестах через

Environment.Current = new MockedEnvironment();

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

1 голос
/ 15 мая 2009

Можете ли вы скрыть статический метод за абстрактным интерфейсом?

interface ISupportIPv6
{
  bool supported { get; }
}

//class for unit testing
class TestSupportsIPv6 : ISupportIPv6
{
  public bool supported { get { return true; } }
}

//another class for more unit testing
class TestDoesNotSupportIPv6 : ISupportIPv6
{
  public bool supported { get { return false; } }
}

//class for real life (not unit testing)
class OsSupportsIPv6 : ISupportIPv6
{
  public bool supported { get {
    return System.Net.Sockets.Socket.OSSupportsIPv6; } }
}
0 голосов
/ 15 мая 2009

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

Тем не менее, теперь определите, что означает "действительный"? Вы, конечно, можете проверить его правильность: [0-9] {1,3} - это начало регулярного выражения для этого.

Вы можете проверить, что это достижимо с помощью эхо-пакета ICMP (или ping (8)).

Если вы можете определить, что значит «действительный» для вас, это должно определить юнит-тест.

0 голосов
/ 15 мая 2009

Я не понимаю, почему ты не смеешься над этим. Ваш метод должен принимать параметр bool SupportsIPv6, а в реальном коде вы передаете его System.Net.Sockets.Socket.OSSupportsIPv6. Затем вы тестируете свой метод с вашим параметром, равным true и false, и убедитесь, что он выдает правильные форматы как для true, так и для false случаев. Вуаля, готово.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...