【问题标题】:Return a value based on other method input根据其他方法输入返回一个值
【发布时间】:2014-06-30 15:01:26
【问题描述】:
我正在尝试模拟一个非常简单(简化)的接口,它基本上是缓存服务的接口:
public interface ICache
{
T Get<T>(String key);
T Set<T>(String key, T value); // return T on success or null on fail
}
我想通过以下方式使用 Moq 模拟这个:
- 如果我用尚未设置的键调用
Get,它应该返回null
- 如果我使用键“x”和值“y”调用
Set,然后然后调用Get
键'x',它应该返回'y'
- 如果我用值“z”覆盖键“x”,然后调用
Get
使用键“x”,它应该返回新值“z”而不是“y”。
我知道我可以创建一个实现接口并使用字典的假对象,但我想知道这是否可以使用 Moq 轻松完成。谢谢!
【问题讨论】:
标签:
c#
unit-testing
mocking
moq
【解决方案1】:
对我来说,您所描述的行为暗示了一个潜在的字典。但对于一个简单的单元测试,我可能会调用两次Setup 来管理这些期望。
mockCache.Setup(c => c.Get(It.Is<string>(x))).Returns(y);
//...other code
mockCache.Object.Set(x, z);
mockCache.Setup(c => c.Get(It.Is<string>(x)).Returns(z);
//...other code
【解决方案2】:
您可以通过访问字典的回调来做到这一点:
var dictionary = new Dictionary<string, object>();
var mock = new Mock<ICache>(MockBehavior.Strict);
mock.Setup(c => c.Set(It.IsAny<string>(), It.IsAny<object>()))
.Callback((string k, object v) => dictionary[k] = v)
.Returns((string k, object v) => v);
mock.Setup(c => c.Get<object>(It.IsAny<string>()))
.Returns((string k) => dictionary.ContainsKey(k) ? dictionary[k] : null);
const string fooString = "foo";
const string barString = "bar";
mock.Object.Set(fooString, (object)barString);
var bar = mock.Object.Get<object>(fooString);
Assert.AreEqual(barString, bar);
但这不可重复使用,因为您必须为每个执行此类操作的测试复制粘贴它。
封装这种行为的假货似乎是要走的路。