我想测试一个构造,该构造在其中调用一个方法两次以获得两个不同的值
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()
未通过测试?
答案 0 :(得分:5)
如果使用MOQ 4,可以使用SetupSequence,否则可以使用lambda
完成使用SetupSequence非常自我解释。
使用lambdas不是太乱。重要的一点是,在声明设置时,返回值设置为。如果一个人刚刚使用
mockFoo.Setup(mk => mk.Bar()).Returns(pieces[pieceIdx++]);
设置将始终返回片段[0]。通过使用lambda,延迟评估直到调用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());
}
答案 1 :(得分:2)
Moq documentation说可以使用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 proposes在他的博客文章中更好一点,聪明地使用队列:
var values = new Queue<string> { "Canada", "Motion" };
mock.Setup(m => m.getValueByCode(It.IsAny<int>(), It.IsAny<string>()))
.Returns(() => values.Dequeue());
拨打mock.Object.getValueByCode
两次,分别会生成"Canada"
和"Motion"
个字符串。