5

その中でメソッドを 2 回呼び出して 2 つの異なる値を取得する構造をテストしたい

public class  stubhandler
{

public stubhandler()
{

string codetext = model.getValueByCode(int a,string b); // 1,"High"    result Canada
string datatext = model.getValueByCode(int a,string b); // 10, "Slow"   result Motion

}

}

上記をテストするには、ユニットテストクラスを使用します

[TestMethod]
public void StubHandlerConstructor_Test()
{
Mock<Model> objMock = new Mock<>(Model);
objMock.Setup(m => m.getValueByCode(It.IsAny<int>,It.IsAny<string>)).Returns("Canada");

objMock.Setup(m => m.getValueByCode(It.IsAny<int>,It.IsAny<string>)).Returns("Motion");

stubhandler  classstubhandler = new stubhandler();

}

上記のメソッドはパスしますが、codetext と datatext には同じ値が含まれています Motion に設定したい

codetext = Canada
datatext = Motion

どうすればこれを達成できますか?

テストに失敗したものを試しobjMock.VerifyAll()ましたか??

4

2 に答える 2

5

MOQ 4 を使用する場合は、SetupSequence を使用できます。そうでない場合は、ラムダを使用して実行できます。

SetupSequence の使い方は一目瞭然です。

ラムダの使用はそれほど面倒ではありません。重要な点は、setup が宣言された時点で戻り値が設定されるということではありません。使用したばかりの場合

mockFoo.Setup(mk => mk.Bar()).Returns(pieces[pieceIdx++]);

セットアップは常にpieces[0]を返します。ラムダを使用すると、Bar() が呼び出されるまで評価が延期されます。

public interface IFoo {
    string Bar();
}

public class Snafu {

    private IFoo _foo;
    public Snafu(IFoo foo) {
        _foo = foo;
    }

    public string GetGreeting() {
        return string.Format("{0} {1}",
                             _foo.Bar(),
                             _foo.Bar());
    }

}

[TestMethod]
public void UsingSequences() {

    var mockFoo = new Mock<IFoo>();
    mockFoo.SetupSequence(mk => mk.Bar()).Returns("Hello").Returns("World");

    var snafu = new Snafu(mockFoo.Object);

    Assert.AreEqual("Hello World", snafu.GetGreeting());

}

[TestMethod]
public void NotUsingSequences() {

    var pieces = new[] {
            "Hello",
            "World"
    };
    var pieceIdx = 0;

    var mockFoo = new Mock<IFoo>();
    mockFoo.Setup(mk => mk.Bar()).Returns(()=>pieces[pieceIdx++]);

    var snafu = new Snafu(mockFoo.Object);

    Assert.AreEqual("Hello World", snafu.GetGreeting());

}
于 2012-09-26T11:56:18.320 に答える
2

Moq のドキュメントでは、次のメソッドを使用して、連続したリターンのようなものをシミュレートできると述べています。Callback

var values = new [] { "Canada", "Motion" };
int callNumber = 0;

mock.Setup(m => m.getValueByCode(It.IsAny<int>(), It.IsAny<string>()))
    .Returns((i,s) => values[callNumber])
    .Callback(() => callNumber++);

これで問題は解決しますが、最も洗練されたソリューションではありません。Matt Hamilton は、彼のブログ投稿で、キューを巧みに使用して、はるかに優れた方法を提案しています。

var values = new Queue<string> { "Canada", "Motion" };

mock.Setup(m => m.getValueByCode(It.IsAny<int>(), It.IsAny<string>()))
    .Returns(() => values.Dequeue());

2 回呼び出すと、それぞれ文字列と文字列mock.Object.getValueByCodeが生成されます。"Canada""Motion"

于 2012-09-26T11:54:28.663 に答える