如何编写一般函数回调测试类?

时间:2014-06-12 14:39:03

标签: c++ unit-testing templates

我有几个类,每个类都存储并调用回调函数。回调函数的签名具有不同的参数和返回类型,但它们只需要一个参数。

要验证这些类是否应该调用它们的回调,我正在尝试编写一个通用测试类,其中(1)提供一个带有一个参数的回调函数,(2)让用户查询该函数是否已经调用,(3)让用户检查传递给该函数的参数。到目前为止,我有这样的事情:

template<class ReturnType, class ParameterType> class Callable
{
    public:
        Callable() : m_called(false), m_param() {}
        ReturnType operator()(ParameterType param)
        {
            m_called = true;
            m_param = param;
            return Returntype();
        }
        bool Called() { return m_called; }
        ParameterType Param() { return m_param; }

    private:
        bool m_called;
        ParameterType m_param;
};

这是一个可以使用Callable类测试的类:

#include <boost/function.hpp>

class ToBeTested
{
    ToBeTested(boost::function<bool (int)> callback) : m_callback(callback) {};
    boost::function<bool (int)> m_callback;

    //  (methods which should cause the callback to be called here)
};

这是一些测试代码:

#include <boost/bind.hpp>

int main(int, char**)
{
    Callable<bool, int> callable;
    ToBeTested tbt(boost::bind(&Callable<bool, int>::operator());

    //  (tell tbt it should call its callback here)

    if (callable.Called()
    {
        if (EXPECTED_VALUE == callable.Param();
        return 0;
    }

    return -1;
}

这给了我(1)和(2),但是当回调通过引用获取其参数时,(3)存在问题:Callable :: m_param是引用类型,因此不能默认初始化。我可以通过使Callable :: operator()通过引用获取其参数来解决这个问题,如下所示:

    ReturnType operator()(ParameterType & param)

...但是当回调函数按值获取其参数时,我不能使用类Callable。

有没有办法让我的测试类工作,无论回调函数是通过引用获取其参数,还是我需要编写两个几乎相同的测试类?

1 个答案:

答案 0 :(得分:1)

你可以尝试这样的东西,其中引用实际存储为指针:

template<typename T>
struct ref_to_ptr
{
    typedef T type;

    static T wrap(T x) { return x; }
    static T unwrap(T x) { return x; }
};

template<typename T>
struct ref_to_ptr<T&>
{
    typedef T* type;

    static T* wrap(T& x) { return &x; }
    static T& unwrap(T* x) { return *x; }
};

template<class ReturnType, class ParameterType> class Callable
{
    public:
        Callable() : m_called(false), m_param() {}
        ReturnType operator()(ParameterType param)
        {
            m_called = true;
            m_param = ref_to_ptr<ParameterType>::wrap(param);
            return Returntype();
        }
        bool Called() { return m_called; }
        ParameterType Param() { return ref_to_ptr<ParameterType>::unwrap(m_param); }

    private:
        bool m_called;
        typename ref_to_ptr<ParameterType>::type m_param;
};