9

オブジェクトを置き換えて、さまざまなオブジェクトのシーケンスを返したい。例えば:

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、exceptionの順に戻ります。

またはこのようなもの:

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

resourceString、例外、resourceString2の順に返されます。

どうやってやるの?

4

4 に答える 4

26

これは、非常に使いやすいインターフェイスを備えたNSubstituteでサポートされる機能になりました。

それは次のようなものになります...

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

ドキュメントはここにあります

于 2016-07-17T17:54:46.907 に答える
14

この答えは時代遅れです—NSubstituteは現在これを直接サポートしています。詳細については、この質問に対する@dangerdexの回答を参照してください。


NSubstituteの複数戻り構文は、値のみをサポートします。また、例外をスローするには、関数をに渡し、Returns必要なロジックを自分で実装する必要があります(例Returns(x => NextValue()))。

キューを使用したHaackedのブログにMoqシーケンスの関連例があります。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()(); }
}

お役に立てれば。

于 2012-08-29T00:06:26.200 に答える
3

これは、追加のクラスなしですべてをインラインで実行する例です。あなたがこれをたくさんやっていたなら、私はおそらく別のクラスオプションで行くでしょう。

[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();
}
于 2012-08-29T01:19:49.547 に答える
0

パラメータなしの別の例。さらに、関数が分離されたスレッドで定期的に呼び出されるシナリオでは便利です。各呼び出しを異なる方法でシミュレート/モックすることができます。

   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(outリストの結果);

于 2014-09-17T14:13:56.313 に答える