使用输入迭代器时的单元测试

时间:2012-06-26 21:04:52

标签: c++ unit-testing tdd

让我假装下面的C级非常慢,我不希望它在我的单元测试中。所以我创建了一个MockC,它最终将实现与C类相同的接口。

class IC
{
public:
    virtual std::string getName() = 0;
};

class C: public IC
{
public:
    C(){}
    C(int c) : _c(c){}
    int _c;
    virtual std::string getName()
    {
        // do really slow stuff with an external library
        ...
    }
};

class MockC: public IC
{
public:
    MockC(){}
    MockC(int c) : _c(c){}
    int _c;
    virtual std::string getName()
    {
       ...
    }
};

我还有一个精简的输入迭代器,在取消引用时会创建一个Value类型的对象(可能是C或MockC):

template<class Value>
class GetNextIterator 
{
public:
    typedef int (*GetNext)();

    GetNextIterator(GetNext getNext): _getNext(getNext)
    {
        _current = _getNext();
    }

    const Value* operator->() const
    {
        return new Value(_current);
    }

protected:
    int _current;
    GetNext _getNext;
};

int count = 0;
int getNext()
{
    return count++;
}

然后我有一个非常慢的类,它是C类对象的父类,但它也有自己的属性,如下所示:

class ID
{
public:
    virtual std::string getName() = 0;
};

class D: public ID
{
public:
    typedef GetNextIterator<C> Iterator;

    virtual ChildIterator begin() const
    {
        return Iterator(getNext);
    }

    virtual std::string getName()
    {
        // again really slow and accessing external dependencies
        ...
    }
};

现在我该如何测试以下功能,仅作为示例:

int f(D* d)
{
    D::ChildIterator i = d->begin();
    if (d.getName() == "something or other")  
        return i->_c;
    else
        return 1;
}

请记住,我不希望使用具体的C或D类。我应该怎样做才能完全单元测试f()和类似的函数?我完全愿意重新设计上面的任何代码,以便使用单元测试。

1 个答案:

答案 0 :(得分:1)

只模拟你需要模拟的东西。为了测试f()的行为,您可以通过模拟重C对象来走上正确的轨道。您必须编写足够的测试用例来涵盖您认为f()需要处理的任何行为。但是你不需要模拟容器本身,这应该是容易测试的。所以,摆脱IContainer概念。

但是,你需要修改Container,使其接受IC对象的输入而不是具体的对象(你也不需要这个是基于模板的,如果只是为了测试,Container可以保持文字{{1 }})。测试代码和生产代码都将为IC*提供一个真正的Container对象。测试代码将首先使用MockC对象填充Container,而生产代码将在调用f()之前填充带有C对象的Container。