单元测试使用API​​的代码

时间:2010-11-25 18:34:42

标签: unit-testing dependency-injection moq integration-testing

我有这个简单的方法调用TFS(Team foundation server)API来获取WorkItemCollection对象。我刚刚转换为实体类,并将其添加到缓存中。如你所见,这很简单。

我应该如何对这种方法进行单元测试。它唯一重要的一点就是调用TFS API。值得测试这样的方法吗?如果是,那么我们应该如何测试呢?

我可以想到的一种方法是我可以模拟调用Query.QueryWorkItemStore(查询)并返回类型为“WorkItemCollection”的对象,最后看到此方法将“WorkItemCollection”转换为List。并检查它是否已添加到缓存中。

另外,因为我正在使用依赖注入模式,所以我正在为

注入依赖
  • 缓存
  • 查询

我应该只传递模拟类型的依赖关系(使用MOQ),或者我应该传递正确的类类型。

public virtual List<Sprint> Sprint(string query)
{
    List<Sprint> sprints = 
        Cache.Get<List<Sprint>>(query);

    if (sprints == null)
    {
        WorkItemCollection items = 
            Query.QueryWorkItemStore(query);
        sprints = new List<Sprint>();

        foreach (WorkItem i in items)
        {
            Sprint sprint = new Sprint
            {
                ID = i.Id,
                IterationPath = i.IterationPath,
                AreaPath = i.AreaPath,
                Title = i.Title,
                State = i.State,
                Goal = i.Description,
            };

            sprints.Add(sprint);
        }

        Cache.Add(sprints, query, 
            this.CacheExpiryInterval);
    }

    return sprints;
}

1 个答案:

答案 0 :(得分:3)

  

我应该只传递模拟类型的依赖关系(使用MOQ),或者我应该传递正确的类类型。

在你的单元测试中,你应该传递一个模拟。有几个原因:

  • 模拟透明:它允许您检查测试中的代码是否使用模拟做了正确的事情。
  • 模拟为您提供完全控制,允许您测试使用真实服务器难以或无法创建的方案(例如,抛出IOException
  • 模拟可预测。真正的服务器不是 - 在运行测试时甚至可能无法使用。
  • 你在模拟上做的事情不会影响外面的世界。您不希望通过运行测试来更改数据或使服务器崩溃。
  • 使用模拟测试更快。不必与服务器或真实数据库查询建立连接。

话虽这么说,包括真实服务器的自动化集成测试也非常有用。您只需要记住,它们将具有较低的代码覆盖率,将更加脆弱,并且创建/运行/维护将更加昂贵。将您的单元测试和集成测试分开。

编辑一些协作者对象(如您的Cache对象)也可能非常适合单元测试。如果它们具有与我上面列出的模拟相同的优点,那么您不需要创建模拟。例如,您通常don't need to mock a collection