0

我想对一个看起来像这样的类进行单元测试:

template <typename T>
class MyClass {
...
    void someMethod() {
        T object;
        object.doSomething();
    }
...
};

我想对这个类进行单元测试,所以我为 T 创建了一个模拟类:

struct MockT {
...
    MOCK_METHOD(doSomething, 0, void());
...
};

然后我想在测试用例中使用它:

BOOST_AUTO_TEST_CASE(testSomeMethod) {
    MyClass<MockT> myClassUnderTest;
    MOCK_EXPECT(???)....;
    myClassUnderTest.someMethod();
}

我如何对这个对象做出期望?我的第一个想法是将所有创建MockT的实例存储在构造函数的静态容器中,然后从析构函数的容器中删除它们。如果对象是用不同于使用它的方法创建的,这将起作用,如下所示:

myClassUnderTest.createTheObject();
MOCK_EXPECT(MockT::findMyObject().doSomething);
myClassUnderTest.useTheObject();

但是为此我需要修改我的类的接口,我真的不想这样做。还有什么我可以做的吗?

4

3 回答 3

3

如果您不想修改接口或引入额外的间接性,可以使用 Typemock Isolator++。

template <typename T>
class MyClass
{
public:
    void someMethod()
    {
        T object;
        object.doSomething();
    }
};

    class RealType  //RealType is the actual production type, no injection needed
    {
    public:
        void doSomething(){}
    };

由于 T 是在 someMethod 内部创建的(在被测方法内部),我们需要伪造 T 的 ctor。FAKE_ALL 就是这样做的。fakeRealType 上设置的行为将适用于在运行时创建的所有 RealType 实例。默认的 FAKE_ALL 行为是递归伪造,这意味着所有伪造的方法都是伪造的,并将返回伪造的对象。您还可以在任何方法上手动设置您想要的任何行为。

TEST_CLASS(MyTests)
    {
    public:

        TEST_METHOD(Faking_Dependency_And_Asserting_It_Was_Called)
        {
            RealType* fakeRealType= FAKE_ALL<RealType>();
            MyClass<RealType> myClassUnderTest;
            myClassUnderTest.someMethod();

            ASSERT_WAS_CALLED(fakeRealType->doSomething()); 
        }

    };

Typemock fakes 并不严格,所以你需要编写一个适当的断言来确保你的方法确实被调用了。您可以使用 Typemock 提供的 ASSERT_WAS_CALLED 来完成。

PS我使用MSTest。

于 2015-04-15T08:30:10.493 回答
1

您可以将 doSomething 成员函数重定向到静态成员函数,例如

struct MockT
{
    void doSomething() {
        soSomethingS();
    }
    MOCK_STATIC_FUNCTION( doSomethingS, 0, void(), doSomething )
};

那么你的测试将是

BOOST_AUTO_TEST_CASE(testSomeMethod) {
    MyClass<MockT> myClassUnderTest;
    MOCK_EXPECT(MockT::doSomething).once();
    myClassUnderTest.someMethod();
}

如果需要,您可以测试对象实例的构造销毁,但它可能不会为您的测试带来更多。

于 2015-03-23T05:34:13.957 回答
0

我发现最好的方法是为成员使用共享指针。不幸的是,由于单元测试,我不得不使用额外的间接,但至少它运作良好。

template <typename T, typename TFactory>
class MyClass {
...
    void someMethod() {
        std::shared_ptr<T> object = factory();
        object->doSomething();
    }
...
    TFactory factory;
};

然后在测试中它看起来像这样:

BOOST_AUTO_TEST_CASE(testSomeMethod) {
    std::shared_ptr<T> mockT;
    MockTFactory factory(mockT);
    MyClass<MockT, MockTFactory> myClassUnderTest(factory);
    MOCK_EXPECT(mockT->doSomething).once();
    myClassUnderTest.someMethod();
}
于 2015-03-26T19:18:12.977 回答