Moq验证失败

时间:2013-09-25 22:24:53

标签: c# moq

我知道这个问题在这里被问了太多次,但我仍然无法弄清楚我的代码有什么问题。

我有一个实现单例的类。该类使用Web服务代理来访问数据。数据被缓存,2个后续调用应该导致对服务的单次调用。它确实有效,我可以在单步执行时看到它,但测试失败了。

[Test]
public void Test1()
{
    Mock<IAtomService> atomService = new Mock<IAtomService>();
    atomService.Setup(x => x.Get(It.IsAny<List<Identifier>>(), It.IsAny<AtomReturnFormat>()))
               .Returns<List<Identifier>, AtomReturnFormat>(
                   (list, format) => new AtomList { Atoms = new AtomCollection(list.Select(ident => new Atom { ID = Guid.Parse(ident.ID) })) });

    AtomCache.Instance.AtomService = atomService.Object;

    Guid id = Guid.NewGuid();
    List<string> ids = new List<string> { id.ToString() };

    AtomCache cache1 = AtomCache.Instance;
    cache1.Get(ids);

    AtomCache cache2 = AtomCache.Instance;
    cache2.Get(ids);

    AtomService.Verify(x => x.Get(It.IsAny<List<Identifier>>(), It.IsAny<AtomReturnFormat>()), Times.Once());
}

错误是

Expected invocation on the mock once, but was 0 times: x => x.Get(It.IsAny<List`1>(), It.IsAny<AtomReturnFormat>())

Configured setups:
x => x.Get(It.IsAny<List`1>(), It.IsAny<AtomReturnFormat>()), Times.Never
No invocations performed.

非常感谢任何帮助

更新

    public List<Atom> Get(List<string> atomIds)
    {
        if (atomIds == null)
            throw new ArgumentNullException("atomIds");

        Dictionary<string, Atom> cachedAtoms = Cache.Get(atomIds.Where(id => !string.IsNullOrEmpty(id)).Distinct().ToList());

        List<Atom> atoms = new List<Atom>();
        if (cachedAtoms != null)
        {
            List<string> missingAtomIds = atomIds.Except(cachedAtoms.Keys).ToList();
            atoms.AddRange(getMissingAtoms(missingAtomIds));

            atoms.AddRange(cachedAtoms.Where(kv => kv.Value != null).Select(kv => kv.Value));
        }
        return atoms;
    }

    private IEnumerable<Atom> getMissingAtoms(List<string> atomIds)
    {
        if (atomIds == null)
            throw new ArgumentNullException("atomIds");

        List<Atom> atoms = new List<Atom>();
        if (atomIds.Count > 0)
        {
            List<Atom> list = retrieveAtoms(atomIds);
            Cache.Add(list);
            atoms.AddRange(list);
        }

        return atoms;
    }

    private List<Atom> retrieveAtoms(List<string> atomIDs)
    {
        if (atomIDs == null)
            throw new ArgumentNullException("atomIDs");

        if (AtomService == null)
            throw new ApplicationException("AtomCache: Atom Service proxy is not initialized.");

        Guid temp;
        List<Identifier> idList = atomIDs.Where(id => !string.IsNullOrWhiteSpace(id) && Guid.TryParse(id, out temp))
                                         .Select(id => new Identifier {ID = id, Type = IdentifierTypeEnum.AtomPrimary})
                                         .ToList();

        List<Atom> atoms = atomIDs.Count == 0
                               ? new List<Atom>()
                               : ((AtomList) AtomService.Get(idList, AtomReturnFormat.Complete)).Atoms.ToList();

        return atoms;
    }

2 个答案:

答案 0 :(得分:0)

除非我错过了更新中的更改内容,否则我认为您就是问题所在。

在您的设置中,如果传递了标识符列表,则告诉模拟返回的内容:

atomService.Setup(x => x.Get(It.IsAny<List<Identifier>>(), %<--snip--

然而,当你打电话时,你传递的是一串字符串:

List<string> ids = new List<string> { id.ToString() };

AtomCache cache1 = AtomCache.Instance;
cache1.Get(ids);

我没有看到这个字符串列表被转换为标识符列表的任何地方,因此模拟永远不会满足您的设置条件,即:当被要求提供任何标识符列表时,因此它正确报告它是问过0次。

答案 1 :(得分:0)

我弄清楚问题是什么。这是我称为验证的模拟的另一个实例。当我在这里复制代码时,我简化了代码并修复了错误:)

谢谢