Использование Moq для проверки выполнения приватных методов - PullRequest
5 голосов
/ 27 июля 2011

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

public void myPublicMethod(params) {

    if(some_condition)
        privateMethod1();
    else
        privateMethod2();
} 

У меня есть все другие зависимости в методе, и яустановите это так, чтобы я мог гарантировать, что some_condition имеет значение true.Я хочу убедиться, что мой privateMethod1 () вызывается ровно один раз, а privateMethod2 () вообще не вызывается.Можно ли это сделать с Moq?

Вот несколько замечаний по этому вопросу:

  • privateMethod1 () и privateMethod2 () находятся в одном классе с myPublicMethod, поэтому я могу 't создать фиктивный объект для этого класса.
  • Тела privateMethod1 / 2 содержат много-много зависимостей от класса, который содержит их, и myPublicMethod, так что разбиение privateMethod1 / 2 на их собственный вспомогательный класс будет непозволительнотрудоемкий

Есть мысли?Заранее спасибо.Я готов согласиться с тем, что этого нельзя сделать, но я хотел бы узнать так или иначе.

Ответы [ 2 ]

15 голосов
/ 27 июля 2011

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

Построение тестов на частных методах приведет к хрупким тестам, которые легко ломаются при рефакторинге частных реализаций (для производительности или другихпричины).

4 голосов
/ 07 июля 2012

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

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

private Action Behavior1;
private Action Behavior2;

В конструкторе класса нормальное поведение реализовано так:

public Foo (...)
{
    Behavior1 = privateMethod1;
    Behavior2 = privateMethod2;
...
}

В публичном методе делегат вызывается вместо фактического метода:

public void myPublicMethod(params) {
    if(some_condition)
        Behavior1();
    else
        Behavior2();
} 

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

Итак, теперь в тесте после создания экземпляра тестового объекта вы можете переопределить зависимое поведение:

Foo_Accessor testMe = new Foo_Accessor();

bool wasCalled1 = false

testMe.Behavior1 = new Action(() => wasCalled1 = true);

...

Assert.IsTrue(wasCalled1);
...