根据其他方法输入返回值

时间:2014-06-30 15:01:27

标签: c# unit-testing mocking moq

我正在尝试模拟一个非常简单(简化)的界面,它基本上是一个缓存服务的接口:

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'。

我知道我可以创建一个实现接口并使用Dictionary的假对象,但我想知道是否可以使用Moq轻松完成。谢谢!

2 个答案:

答案 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);

但这并不可重复使用,因为您必须为每个执行此类测试的测试进行复制。

伪造这种行为的假装似乎是要走的路。