NSubstitute When...Do определение не переопределяется последующими определениями

void ABC()
{
    var foo = Substitute.For<IFoo>();
    foo.When(x => x.Bar()).Do(x => counter++);
    <use Bar()>.... 1
    foo.When(x => x.Bar()).Do(x => counter--);
    <use Bar()>.... 2
}

Для приведенного выше фрагмента кода (1) и (2) отображено поведение counter++, указывающее, что поведение When...Do не переопределяется. Мне нужно это поведение для генерации моего сценария тестирования, где я хочу подключить различные обратные вызовы.

Как мне этого добиться?

1 ответ

Решение

Do обратный вызов не заменяется, но оба должны выполняться. Например (используя NSub 1.4.3.0):

var counter = 0;
var sub = Substitute.For<IFoo>();
sub.When(x => x.Bar()).Do(x => counter++);
sub.Bar();
Console.WriteLine(counter);  // prints 1
sub.When(x => x.Bar()).Do(x => counter--);
sub.Bar();
Console.WriteLine(counter);  // prints 1, as counter gets inc'd to 2, then dec'd to 1

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

С этим отказом от ответственности один из способов поменять обратные вызовы - использовать вспомогательный класс для предоставления определенного обратного вызова:

[Test]
public void Example() {
    var counter = 0;
    var helper = new CallbackHelper();
    helper.Callback = x => counter++;
    var sub = Substitute.For<IFoo>();

    sub.When(x => x.Bar()).Do(x => helper.Callback(x));
    sub.Bar();
    Console.WriteLine(counter);

    helper.Callback = x => counter--;
    sub.Bar();
    Console.WriteLine(counter);

    helper.Callback = x => { counter = (counter+1) * 10; };
    sub.Bar();
    Console.WriteLine(counter);
}

public class CallbackHelper {
    public Action<CallInfo> Callback;
}

/* Prints:
    1
    0
    10
*/

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

Надеюсь это поможет.:)

Другие вопросы по тегам