Нужно ли тестировать вспомогательные методы / методы настройки? - PullRequest
3 голосов
/ 17 июня 2009

Итак, у меня есть вспомогательный метод, который выглядит примерно так:

private D GetInstanceOfD(string param1, int param2)
{
    A a = new A();
    B a = new B();
    C c = new C(a,b, param1);

    return new D(c, param2);
}

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

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

Если ответ на первый вопрос - да, мой второй: как? В настоящее время я использую NUnit и RhinoMocks и пытаюсь понять, как этот метод должен быть подвергнут рефакторингу, чтобы быть тестируемым (ну, и нужно ли что-то подобное проверять!) Внедрение зависимостей здесь, очевидно, не сработает, так как этот метод фактически создает зависимости!

Или этот метод плохой, и я должен сделать что-то вроде следующего:

D d = new (new C(new A(), new B(), "string"), 1024);

Ответы [ 5 ]

3 голосов
/ 17 июня 2009

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

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

  • Что произойдет, если я передам ноль для первого параметра?
  • Что произойдет, если я передам отрицательное число для второго параметра?
  • Действительно ли GetInstanceOfD возвращает D в ожидаемых вами случаях?
  • Имеет ли D правильные значения для данного входа.
  • А как насчет экземпляров C, A и B, если они доступны?
2 голосов
/ 17 июня 2009

Когда вы сталкиваетесь с подобными вопросами, следует помнить одну вещь: держать вещи тривиальными .

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

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

1 голос
/ 17 июня 2009

Вы должны проверить этот метод. Вы должны проверить это, поскольку это может потерпеть неудачу; одна пословица XP - Проверьте все, что может сломаться .

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

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

//--- don't write this, you'll probably regret it ;o)
D d = new (new C(new A(), new B(), "string"), 1024);
1 голос
/ 17 июня 2009

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

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

Это определенно было бы таким же направлением, как если бы код был рабочим кодом. Пример ниже:

public class ObjectFactory 
{
     public virtual A CreateA() { return new A(); }
     public virtual B CreateB() { return new B(); }
     public virtual C CreateC( string str ) { return new C( CreateA(), CreateB(), str );
     public virtual D CreateD( string str, int num )
     {
         return new D( CreateC( str ), num );
     }
}


public class Foo
{
    private ObjectFactory ObjectFactory { get; set; }

    public Foo() : this(null) { }
    public Foo( ObjectFactory factory )
    {
         this.ObjectFactory = factory ?? new ObjectFactory();
    }

    public void Bar()
    {
        D objD = this.ObjectFactory.CreateD( param1, param2 );
    }
}

[TestMethod]
public void TestBar()
{
     var factory = MockRepository.GenerateMock<ObjectFactory>();
     var d = MockRepository.GenerateMock<D>();
     factory.Expect( f => f.CreateD( "abc", 10 ) ).Return( d );

     var foo = new Foo( factory );

     foo.Bar();

     factory.VerifyAllExpectations();
     d.VerifyAllExpectations();
}
0 голосов
/ 17 июня 2009
Методы

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

Этот метод чувствует, что он принадлежит классу фабрики или компоновщика, а не частному методу. Он не будет элегантно тестируемым, если вы будете хранить скрытый код как частный метод.

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