アプリケーションのテストを開発しています。パラメータとしてparams
配列を持つメソッドがあります。 Moqを使用してメソッドを設定しましたが、テストを実行すると、メソッドの戻り値はnullです。つまり、モックされていません。
ここにコードサンプルがあります:
public interface ITicketManager {
string GetFirstTicketInQueueIfMatches(params string[] ticketsToMatch);
}
public class TicketManager : ITicketManager {
private Queue<string> ticketQueue = new Queue<string>();
public string GetFirstTicketInQueueIfMatches(params string[] ticketsToMatch) {
var firstQueuedTicket = ticketQueue.Peek();
var firstQueuedTicketMatchesAnyOfRequested = ticketsToMatch.Any(t => t == firstQueuedTicket);
if(firstQueuedTicketMatchesAnyOfRequested)
return firstQueuedTicket;
return null;
}
}
モックコードは次のようになります。
var mock = new Mock<ITicketManager>();
mock.Setup(m => m.GetFirstTicketInQueueIfMatches(It.IsAny<string>()))
.Returns(p => {
if(p.Contains("A"))
return "A";
return null;
});
なぜそれが偽のメソッドに当たらないのですか?
配列ではなく単一の文字列を取るメソッドを呼び出そうとしています。 params
部分を処理するのはC#コンパイラであり、個々の値を指定する呼び出しコードを配列で渡す呼び出しに変換することを覚えておいてください。メソッド自体に関する限り、それは単に配列を取得しているだけであり、それがあなたがモックしているものです。
コンパイラは実際にコードを次のように変換します。
mock.Setup(m => m.GetFirstTicketInQueueIfMatches
(new string[] { It.IsAny<string>() }))
それはあなたが望むものではありません。
あなたは使うべきです:
mock.Setup(m => m.GetFirstTicketInQueueIfMatches(It.IsAny<string[]>()))
単一の値のみが与えられることを確認する必要がある場合は、params以外のパラメーターの場合と同じ方法で行う必要があります。
基本的に、params
はC#コンパイラにのみ影響を与えます-moq
には影響しません。
_params string
_はIt.IsAny<string[]>()
ではなくIt.IsAny<string>()
と一致する必要があると思います
以下のコードはMoqを使用して、params引数を持つメソッドにコールバックを設定します。 2番目の引数を配列として定義すると、うまくいきます。
MockLogger
.Setup(x => x.Info(It.IsAny<string>(), It.IsAny<object[]>()))
.Callback<string, object[]>((x, y) => _length = x.Length);