我应该如何使用该API将包装API的对象传递给类?

时间:2010-05-27 01:13:20

标签: c++ unit-testing mocking

这是我今天早些时候提出的问题的修订/更好的书面版本 - 现在该问题已被删除。

我有一个项目,我开始使用Google Mock。我创建了一个类,该类调用Windows API中的函数。我还创建了一个包含Windows API的虚函数的包装类,如Google Mock CheatSheet中所述。然而,我很困惑我应该如何将包装器传递给使用该对象的类。显然该对象需要是多态的,所以我不能通过值传递它,迫使我传递一个指针。这本身并不是问题,但我很困惑谁应该拥有指向包装API的类的指针。

那么......我应该如何将包装类传递给真正的类来促进模拟呢?

这是我的意思的一个例子:

struct A {
    virtual void SomeMethod(int x, int y)
    {
        ::SomeMethod(x, y);
    };
};

class Client
{
    A * method_;
public:
    Client(A * method = new A) : method_(method) {};
    void DoSomething()
    {
        method_->SomeMethod(42, 34);
    }
};

struct Mock : public A
{
    MOCK_METHOD2(SomeMethod, void(int, int));
};

TEST(MyTest, MyTestWithMock)
{
    Mock * mock = new Mock();
    EXPECT_CALL(*mock, SomeMethod(42, 34)).Times(1);
    Client client(mock); //Should *client* be responsable for deleting mock?
    client.DoSomething();
};

示例2:

struct A {
    virtual void SomeMethod(int x, int y)
    {
        ::SomeMethod(x, y);
    };
};

class Client
{
    A * method_;
public:
    Client(A * method) : method_(method) {};
    static Client Create()
    {
        static A;
        return Client(&A);
    }
    void DoSomething()
    {
        method_->SomeMethod(42, 34);
    }
};

struct Mock : public A
{
    MOCK_METHOD2(SomeMethod, void(int, int));
};

TEST(MyTest, MyTestWithMock)
{
    Mock  mock;
    EXPECT_CALL(mock, SomeMethod(42, 34)).Times(1);
    Client client(&mock);
    client.DoSomething();
};

3 个答案:

答案 0 :(得分:2)

始终可以选择使用shared_ptr;这肯定会解决所有权问题。

答案 1 :(得分:0)

许多所有权计划都是可能的,但有些计划比其他计划更易于维护。每当一个对象x包含另一个y时,我会问:

谁创建了y?该方也应该销毁y

这种方法的优点是,当一个或两个对象被静态分配时,它的工作原理也一样,而转让所有权的方法必须使用shared_ptr<>或假设是否y动态分配与否。前者引入了开销,而后者则是脆弱的。

如果多个方可以创建对象,就像你的代码当前那样(它可以由调用者或构造函数创建为默认参数),到目前为止最简单的方法是使用shared_ptr<>。但是,如果可能的话,避免不同方可以创建资源的情况是个好主意 - 是“用大象枪射击鼠标”。

答案 2 :(得分:0)

虚拟功能不是执行此操作的唯一方法。您还可以使用有效地为您提供编译时多态性的模板。

struct A {
    virtual void SomeMethod(int x, int y)
    {
        ::SomeMethod(x, y);
    };
};

template <class T>
class Client
{
    T method_;
public:
    Client() : method_(method) {};
    static Client Create()
    {
        return Client();
    }
    void DoSomething()
    {
        method.SomeMethod(42, 34);
    }

    T &GetMethod()
    {
        return method_;
    }
};

struct Mock
{
    MOCK_METHOD2(SomeMethod, void(int, int));
};

TEST(MyTest, MyTestWithMock)
{
    Client<Mock> client;
    EXPECT_CALL(client.GetMethod(), SomeMethod(42, 34)).Times(1);
    client.DoSomething();
};