NSubstitute множественная последовательность возврата

Я хочу заменить объект, чтобы вернуть последовательность разных объектов. Например:

var http = Substitute.For<IHttp>();
http.GetResponse(Arg.Any<string>()).Returns(resourceString, resourceString2);
http.GetResponse(Arg.Any<string>()).Returns(x => { throw new Exception(); });

вернет resourceString, затем resourceString2, а затем исключение.

Или что-то вроде этого:

var http = Substitute.For<IHttp>();
http.GetResponse(Arg.Any<string>()).Returns(resourceString, x => { throw new Exception(); }, resourceString2);

вернет resourceString, затем исключение, затем resourceString2.

Как я могу это сделать?


person Alexandr Nikitin    schedule 28.08.2012    source источник
comment
Я сделал запрос на включение в NSubstitute, чтобы поддержать это.   -  person Alexandr Nikitin    schedule 21.01.2013


Ответы (4)


Этот ответ устарел — теперь у NSubstitute есть прямая поддержка. Дополнительную информацию см. в ответе @dangerdex на этот вопрос.


Синтаксис многократного возврата в NSubstitute поддерживает только значения. Чтобы также генерировать исключения, вам нужно передать функцию Returns и самостоятельно реализовать необходимую логику (например, Returns(x => NextValue())).

Связанный пример для последовательностей Moq можно найти в блоге Haacked с помощью очереди. Вы можете сделать то же самое с NSubstitute (только пример кода, используйте на свой страх и риск :)):

public interface IFoo { int Bar(); }

[Test]
public void Example() {
    var results = new Results<int>(1)
                    .Then(2)
                    .Then(3)
                    .Then(() => { throw new Exception("oops"); });
    var sub = Substitute.For<IFoo>();
    sub.Bar().Returns(x => results.Next());

    Assert.AreEqual(1, sub.Bar());
    Assert.AreEqual(2, sub.Bar());
    Assert.AreEqual(3, sub.Bar());
    Assert.Throws<Exception>(() => sub.Bar());
}

public class Results<T> {
    private readonly Queue<Func<T>> values = new Queue<Func<T>>();
    public Results(T result) { values.Enqueue(() => result); }
    public Results<T> Then(T value) { return Then(() => value); }
    public Results<T> Then(Func<T> value) {
        values.Enqueue(value);
        return this;
    }
    public T Next() { return values.Dequeue()(); }
}

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

person David Tchepak    schedule 29.08.2012
comment
Спасибо, это то, что я искал. - person Alexandr Nikitin; 30.08.2012

Теперь это поддерживаемая функция в NSubstitute с очень дружественным интерфейсом.

Было бы что-то вроде...

var http = Substitute.For<IHttp>();
http.GetResponse(Arg.Any<string>()).Returns(x => resourceString, x => resourceString2, x => { throw new Exception(); });

Документацию можно найти здесь

person dangerdex    schedule 17.07.2016

Вот пример, который делает все встроенным без дополнительного класса. Если бы вы делали это много, я бы, вероятно, выбрал вариант отдельного класса.

[Test]
public void WhenSomethingHappens()
{
    var something = Substitute.For<ISomething>();
    int callCount = 0;
    something.SomeCall().Returns(1, 2);
    something.When(x => x.SomeCall()).Do(obj => { if (++callCount == 3) throw new Exception("Problem!"); });

    Assert.AreEqual(1, something.SomeCall());
    Assert.AreEqual(2, something.SomeCall());
    Assert.Throws<Exception>(() => something.SomeCall());
}


public interface ISomething
{
    int SomeCall();
}
person user1631800    schedule 29.08.2012
comment
Спасибо, способ с дополнительным классом кажется более простым для чтения и реализации. - person Alexandr Nikitin; 30.08.2012

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

   List<AnyClass> items = new List<AnyClass>();

   mockIService.TryDoSth(out response).ReturnsForAnyArgs(p =>
            {
                p[0] = items;
                return true;
            }, 
            p =>
            {
                p[0] = items;
                return true;
            }, p =>
            {
                throw new Exception("Problem!"); 
            });

bool TryDoSth (результат из списка);

person komizo    schedule 17.09.2014