【问题标题】: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);
      

      但这不可重复使用,因为您必须为每个执行此类操作的测试复制粘贴它。

      封装这种行为的假货似乎是要走的路。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-14
        • 1970-01-01
        • 2023-03-19
        • 2020-08-12
        • 2021-08-21
        • 1970-01-01
        • 2019-04-17
        • 1970-01-01
        相关资源
        最近更新 更多