我正在尝试模拟一个非常简单(简化)的界面,它基本上是一个缓存服务的接口:
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
Set
,然后,则拨打Get
键'x',它应该返回'y'Get
使用键'x',它应该返回新值'z'而不是'y'。我知道我可以创建一个实现接口并使用Dictionary的假对象,但我想知道是否可以使用Moq轻松完成。谢谢!
答案 0 :(得分:4)
对我来说,您描述的行为意味着一个基础字典。但是对于一个简单的单元测试,我可能只需要两次调用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
答案 1 :(得分:3)
您可以使用访问字典的回调来执行此操作:
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);
但这并不可重复使用,因为您必须为每个执行此类测试的测试进行复制。
伪造这种行为的假装似乎是要走的路。