I want to test a construct which calls a method within it twice to get two different values
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
}
}
To test the above i use a unit test class
[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();
}
The above method pass but codetext and datatext contains same value Motion i want them to set to
codetext = Canada
datatext = Motion
How can i achieve this?
I have tried objMock.VerifyAll()
which fails the test ??
Moq documentation says you can simulate something like successive returns with Callback
method:
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++);
This will do the trick, but it's not the most elegant solution. Matt Hamilton proposes much better one in his blog post, with clever use of queue:
var values = new Queue<string> { "Canada", "Motion" };
mock.Setup(m => m.getValueByCode(It.IsAny<int>(), It.IsAny<string>()))
.Returns(() => values.Dequeue());
Calling mock.Object.getValueByCode
twice, will produce "Canada"
and "Motion"
strings respectively.
If using MOQ 4 one can use SetupSequence, else it can be done using a lambda
Using SetupSequence is pretty self explanatory.
Using the lambdas is not too messy. The important point to not it that the return value is set at the time that the setup is declared. If one just used
mockFoo.Setup(mk => mk.Bar()).Returns(pieces[pieceIdx++]);
the setup would always return pieces[0]. By using the lambda, the evaluation is deferred until Bar() is invoked.
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());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With