Вопрос по moq, private-members, unit-testing, mocking – Итак, теперь, в тесте, после создания экземпляра тестового объекта, вы можете переопределить зависимое поведение:

5

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

public void myPublicMethod(params) {

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

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

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

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

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

Ваш Ответ

2   ответа
4

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

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

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);
15

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

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

Я не хочу проверять реальный приватный метод; Я просто хочу убедиться, что это называется. PianoFighter88
По сути, я пытаюсь соблюдать действующую политику, которая гласит, что каждое изменение кода требует соответствующего модульного теста (так что, если модульный тест прерывается позже, мы вынуждены действительно подумать, что / почему мы вносим изменение). Моим «изменением кода» была условная логика, которая приводит к вызову одного из двух закрытых методов. PianoFighter88
Но если вы не можете проверить изменение поведения извне, это означает, что никаких реальных изменений нет вообще. Если это только детали реализации, которые не влияют на результат, это должно быть уже охвачено модульными тестами. И модульные тесты должны гарантировать, что такие изменения реализации ничего не сломят. Политика вашей компании, вероятно, должна запрещать изменять функциональность / поведение без покрытия модульного теста, а не без добавления нового модульного теста. NOtherDev
Не уверен, что этот ответ имеет большой смысл. Если d512
А, ваше разъяснение имеет смысл. privateMethod1 и privateMethod2 - это два разных способа сделать одно и то же, и единственное, что меняется, это то, как они работают, чтобы получить один и тот же результат, но сам результат отличается. Спасибо вам и Патрику за помощь. PianoFighter88

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