0

我有以下测试:

TestGet(): _interface(), _db(_interface)
{
    _interface.get = mockGet;
}

在测试此类时使用:

class DB: public IDB
{
public:
   explicit DB(Interface_T& interface):
     _interface(interface)
   {
   }

   ...

private:
   Interface_T _interface;
};

Interface_T 是在结构中实现并从 C api 传递给我的 C 接口。我希望使用 DB 类作为 C 接口的包装器。

但是请注意,DB 将接口对象复制到其成员 _interface。因此该行:

_interface.get = mockGet;

从 DB 对象的角度来看没有影响,尽管这是我编写测试类时的意图。你将如何重写 TestGet() 来纠正这个错误?您将如何向 DB 类的客户端展示它复制传递给它的值?

4

4 回答 4

1

假设您的意图是在使用的对象TestGet上设置一个成员,您可以:Interface_TDB

A. 推迟建设DB

TestGet(): _interface(), _db(NULL)
{
    _interface.get = mockGet;

    // Using a raw pointer here for minimalism, but in practice
    // you should prefer a smart pointer type.
    _db = new DB(_interface);
}

B. 如果你可以控制Interface_T类,你可以添加一个Interface_T::get直接初始化的构造函数。然后你可以这样做:

TestGet(): _interface(mockGet), _db(_interface)
{
}

C. 如果您可以控制DB该类,您可以更改它以共享所提供的所有权Interface_T(例如通过boost::shared_ptr),添加 B 中的构造函数,或为其内部Interface_T成员添加访问器。

于 2012-10-02T09:26:57.123 回答
1

因此,在构建 db get 时,您需要正确的接口。嗯,这很容易。只需在函数中创建适当的接口并将结果传递给构造函数:

Interface_T makeMockInterface()
{
    Interface_T interface;
    // I presume you will first use the C API to initialize it and than
    interface.get = mockGet;
}

TestGet() : _db(makeMockInterface())
{
}

由 from的Interface_T值返回makeMockInterface,但是由于底层机器代码实际上是通过将对象复制到调用者提供的空间来返回对象,因此大多数编译器实际上会省略副本并直接在调用者提供的空间中构造对象(标准明确允许)。

TestGet 类不需要有单独的 _interface 成员,因为 _db 包含它并且它们无论如何都不会被共享,所以没有意义。

编辑:构造DB函数采用非常量引用,即使它所做的只是复制对象并且 const 引用就足够了。修复构造函数会更好,但如果它不是一个选项,我会将它转换为非常量。要么需要两个演员表:

TestGet() : _db(const_cast<Interface_T &>(static_cast<const Interface_T &>(makeMockInterface())))

或一个简单的模板助手:

template <typename T>
T &lvalue_cast(const T &v) { return const_cast<T &>(v); }

TestGet() : _db(lvalue_cast(makeMockInterface()))

由于临时变量实际上是可变的,只是不绑定到非常量引用作为保护,两者都定义明确。

于 2012-10-02T09:43:23.983 回答
0

这是基于上面的 Jan Hudec 评论:

class TestGet : public ::testing::Test 
{
protected:
   TestGet() 
      :  _db(interfaceFactory())
   {
   }

   Interface_T interfaceFactory()
   {
      Interface_T interface;
      _interface.get = mockGet;
      return interface;
   }

   DB _db;
};

我喜欢这种干净的方法。

于 2012-10-02T09:48:57.773 回答
0

有几种方法,都包括某种控制反转

我最喜欢的是:

  • 使用对接口的引用将对象传递给构造函数
  • 使用工厂模式创建对象,并返回某种共享指针(再次使用接口)

像这样的东西(假设你有基本的抽象类):

struct Interface
{
  virtual ~Interface(){}
  virtual void foo() = 0;
};
struct Derived : public Interface
{
  void foo(){}
};

struct A
{
  A ( std::shared_ptr< Interface > obj_ ) : obj( obj_ )
  {}

  std::shared_ptr< Interface > obj;
};

//...
A myA( std::shared_ptr< Interface >( new Derived ) );
// ..

上面的例子是传递给构造函数。

于 2012-10-02T10:59:30.257 回答