2015-04-12 32 views
1

我正在使用Google Test和Google Mock使用测试驱动开发编写代码。我正在为Google Test编写一个小的“插件”。为了确保在正确的信息下测试会失败,我创建了一个简单的FailureReporter类,我将其分类并在插件中插入一个模拟版本以捕获结果并与预期值进行比较。为什么链接顺序会影响使用宏的测试的测试结果?

本着TDD极端主义的精神,我也写了一个测试,以确保FailureReporter的工作。为此,我“替换”了FAIL()宏,以便不会导致失败,而是捕获由此产生的错误消息。但是,这是事情变得奇怪的地方。它在一台机器上工作,但不在另一台机器上。在查找原因时,我发现它可以通过更改链接顺序来解决。这看起来很奇怪,因为“修复”是使用宏来完成的,而且我会假设它在编译时会被硬编码,而将它连接起来也没有什么区别。

我发现的是:链接测试本身没有问题。将它与使用FailureReporter的模拟版本的测试链接仅适用于其他测试链接在FailureReporterTest.之后的情况。为什么会发生这种情况?

FailureReporter.hpp:

#ifndef FAILURE_REPORTER_H 
#define FAILURE_REPORTER_H 

#include "gtest/gtest.h" 

class FailureReporter { 
public: 
    virtual void fail(const char* errorMessage) { 
     FAIL() << errorMessage; 
    } 
}; 

#endif 

FailureReporterTest.cpp:

#include <sstream> 

#include "gtest/gtest.h" 

static std::stringstream* failStream; 

#ifdef FAIL 
#undef FAIL 
#endif 

#define FAIL() *failStream << "" 

#include "FailureReporter.hpp" 

TEST(FailureReporterTest, failMethod) { 
    const char* errorMessage = "Test error message"; 
    FailureReporter *reporter; 
    std::stringstream stream; 

    failStream = &stream; 

    reporter = new FailureReporter(); 

    reporter->fail(errorMessage); 

    EXPECT_STREQ(errorMessage, stream.str().c_str()); 

    delete reporter; 
} 

MockFailureReporter.cpp

#ifndef MOCK_FAILURE_REPORTER_HPP 
#define MOCK_FAILURE_REPORTER_HPP 

#include "gmock/gmock.h" 

#include "FailureReporter.hpp" 

class MockFailureReporter : public FailureReporter { 
public: 
    MOCK_METHOD1(fail, void(const char*)); 
}; 

#endif 

DummyTest.cpp

#include "gtest/gtest.h" 

#include "MockFailureReporter.hpp" 

TEST(DummyTest, dummy) { 
    new MockFailureReporter(); 
    SUCCEED(); 
} 

编译源与

g++ -c DummyTest.cpp 
g++ -c FailureReporterTest.cpp 

并用

g++ DummyTest.o FailureReporterTest.o -pthread -lgtest -lgmock -lgmock_main 

将它们连接起来,生成a.out可执行失败的failMethod测试,而具有

g++ FailureReporterTest.o DummyTest.o -pthread -lgtest -lgmock -lgmock_main 

将它们连接起来产生一个.out可执行两个测试成功的可执行文件。为什么?

回答

2
class FailureReporter { 
public: 
    virtual void fail(const char* errorMessage) { 
    /* code */ 

创建一个隐含inline实施FailureReporter::fail

inline函数被导出。如果链接器看到相同名称和类型的两个inline函数,它将默默丢弃一个函数。如果它们不是完全相同的,那么你的程序就形成了,不需要诊断。

当您仅在一个编译单元中重新定义FAIL()并将其与其他链接关联时,您最终会得到两个定义FailureReporter::fail。他们链接,并且未定义的行为结果。在你的情况下,你会得到其中一个在两种情况下运行,确定连接器选择放弃内联冲突的任意规则。看起来像“保持第一个我看到”。

相关问题