单元测试包含IDictionary的类

时间:2009-01-14 08:19:29

标签: c# unit-testing

我正在创建一个类,用于确定要调用多少个已注册的WCF客户端回调。当客户端向服务器注册时,它会提供它感兴趣的令牌。然后,类在字典中存储令牌到IClientCallback接口的映射。

该方法及其测试类如下所示

public class Router
{
    private IDictionary<int, IClientCallBack> clients;

    public Router()
    {
        clients = new Dictionary<int, IClientCallBack>();
    }

    public Router(IDictionary<int, IClientCallBack> clients)
    {
        this.clients = clients;
    }

    public bool Register(int token, IClientCallBack client)
    {
        if (!clients.ContainsKey(token))
        {
            clients.Add(token, client);
            return true;
        }
        return false;
    }
}

如何测试客户端是否已成功注册到路由器? 我想我可以假设如果函数返回true,它是成功的(但是什么是停止函数体只是“return true;”?)或者我可以将客户端Dictionary注入类的构造函数和我的test我可以检查clients.Count是否等于1,如下所示。

[TestMethod]
public void RegisterTest()
{
    IDictionary<int, IClientCallBack> clients = new Dictionary<int, IClientCallBack>();
    var router = new Router(clients);
    var client = new Mock<IClientCallBack>().Object;
    var success = router.Register(4, client);
    Assert.IsTrue(success);
    Assert.AreEqual(1, clients.Count);
    Assert.AreEqual(clients[4], client);           
}

虽然上面的测试似乎很好,但是使用依赖注入来插入集合似乎有些过分,所以我可以测试它。然而,它确实使测试更容易和更准确(当测试类的其他方法时)。

这是测试此方法的推荐方法,还是过度杀伤?

3 个答案:

答案 0 :(得分:2)

那么,你为什么要关心字典的内容是什么?如果你注射了它,那么你可能会非常关心 - 但那时它是API的一部分。如果你可以在没有构造函数的情况下使用字典,那么只需测试字典内容的实际效果

所以,如果你为同一个令牌调用两次注册,它应该返回false,对吗?做个测试。据推测,还有其他与令牌有关的事情 - 因此在令牌已经注册时以及何时没有注册时进行测试。

这样说:如果有人想使用令牌/客户端对的链接列表重新实现该类,那会破坏该类的有用功能吗?我怀疑不是 - 所以你的测试可能不应该关心。

现在,在我开始听起来过于学术化之前,我不是那些认为单元测试应该始终如一的人,总是只接触公共方法而不关心实现。他们不是黑盒测试。有时知道实现可以使测试一个复杂的逻辑位变得容易得多,即使它通常只是通过实际上更多地解决它的东西暴露。但是在你提出的情况下,我真的只会坚持“就外面的世界所能做的那样做它能做什么”的方法。

答案 1 :(得分:0)

基本上,如果您正在查看内部数据结构,那么您的测试正在检查特定实现,而不是声明该类的预期行为

如果这是我的测试,我宁愿对模拟对象设置一些期望,然后在Router类上调用一些验证这些期望的方法。

答案 2 :(得分:0)

好点Jon。上面的课程与我今天下午的工作尝试略有简化。在实际的测试代码中,我提供了一个或多个令牌来注册IClientCallBack。每个令牌都应该有一个字典条目。想法是Resolve(int token)将返回映射的IClientCallBack ...

如果我的方法是

,那么扔我的是什么
public bool Register(int token, IClientCallBack client)
{
    return true;
}

我的测试将错误地成功。现在,我可以在类中调用另一个方法来验证IClientCallBack是否被正确映射,例如调用Resolve,但是我会在一次测试中测试不同的方法,我认为这很糟糕业力?

以前我刚刚测试过该方法会返回true,但是有声音告诉我,如果我编写方法来传递,它可能不一定按我想要的那样做。

也许我只是弄乱TDD点:)