這是一個更大專案的一部分,但看起來這個檔案會導致問題。
StreamImpl.hpp
class StreamImpl {
...
template <typename Type>
StreamImpl &operator<<(T &&out) noexcept;
...
};
#include "StreamTemplateImpl.cpp"
StreamTemplateImpl.cpp
// Templates implementation needed for test purposes
#include "StreamImpl.hpp"
#include "MockStreamImpl.hpp"
using ::utils::Dispatcher;
using ::mock::MockStreamImpl; // Error here
template <typename Type>
StreamImpl &operator<<(T &&out) noexcept
{
return Dispatcher<MockStreamImpl>::Instance().Get()->OutOperator(out);
}
MockStreamImpl.hpp
#include "StreamImpl.hpp"
namespace mock {
using ::StreamImpl;
class MockStreamImpl {
MOCK_METHOD(...); // Gmock methods
};
} // namespace mock
避免代碼重復的幫助類:
Fixture.hpp
#include "MockStreamImpl.hpp"
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;
class UtStream : public Test {
// Class for setting up mocks and common test data which is used as fixture in tests
StreamImpl kDefaultStream_{};
}
} // namespace fixture
并帶有測驗用例的檔案,它使用 StreamImpl 模擬:
測驗.cpp
#include "Fixture.hpp"
... // Test cases
CMakeLists.txt
add_unit_test(
TEST_NAME
test_unit
TEST_SOURCES
unit_test_source_file.cpp
${SOURCES}/file_to_test.cpp
${MOCKS}/fake_stream_impl.cpp // source file with fake StreamImpl functions implementations which redirects to mocks
INCLUDE_DIRS
${INCLUDES}
${MOCKS}
${UTILS}
${FAKE_STREAM_IMPL_TEMPLATES}
LIBS
gmock
gtest
gtest_main
)
當我嘗試編譯這個時,我得到了
In file included from /path/src/StreamImpl.hpp:281:0,
from /path/test/unit/mocks/MockStreamImpl.hpp:23,
from /path/test/unit/mocks/Fixture.hpp:24,
from /path/test/unit/unit_test_source_file.cpp:23:
/path/test/unit/mocks/fake_templates/StreamTemplateImpl.cpp:25:18: error: '::mock' has not been declared
using ::mock::MockStreamImpl;
所有標題都有保護,所以我不確定回圈依賴,但如果是的話,我會非常感謝你的解釋。
此外,當我在沒有Fixture.hpp(Fixture.hpp內容合并到unit_test_source_file.cpp)的情況下編譯它時,所有構建都完美。
我真的不明白問題出在哪里,并感謝您的幫助。
我看到了很多相關的話題,但似乎都沒有為我提供答案。
uj5u.com熱心網友回復:
你有一個架構問題,你在一個不好的地方抽象了不同型別的流,這不容易被解開。模擬介面與被測代碼過于緊密地交織在一起。你可以解決這個問題,但你最好停下來仔細思考你想要測驗的內容。
旁注排序:
StreamImpl 是個壞主意。
StreamImpl& operator<<(T &&out) noexcept;
是非標準的,并且是您遇到此問題的一部分。如果你使用標準
std::ostream & operator<<(std::ostream & strm, T &&out) noexcept;
并變成你StreamImpl的孩子,std::ostream你可以通過重寫MockStreamImpl它也是一個孩子,std::ostream并完全隱藏流中流的專業化,而不是寫入流的函式。
旁注的旁注:模板化operator<<也不是一個好主意。大多數型別沒有足夠相似的規則可以被通用函式列印。當<<模板嘗試呼叫自身時,這會導致愚蠢的輸出或混淆的錯誤訊息,因為它仍然是最佳匹配。
什么地方出了錯:
如果我們遵循包含并執行替換,我們可以看到編譯器看到的內容:
#include "MockStreamImpl.hpp"
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;
class UtStream : public Test {
// Class for setting up mocks and common test data which is used as fixture in tests
StreamImpl kDefaultStream_{};
}
} // namespace fixture
造成
#include "StreamImpl.hpp"
namespace mock {
using ::StreamImpl;
class MockStreamImpl {
MOCK_METHOD(...); // Gmock methods
};
} // namespace mock
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;
class UtStream : public Test {
// Class for setting up mocks and common test data which is used as fixture in tests
StreamImpl kDefaultStream_{};
}
} // namespace fixture
然后到
class StreamImpl {
...
template <typename Type>
StreamImpl &operator<<(T &&out) noexcept;
...
};
#include "StreamTemplateImpl.cpp"
namespace mock {
using ::StreamImpl;
class MockStreamImpl {
MOCK_METHOD(...); // Gmock methods
};
} // namespace mock
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;
class UtStream : public Test {
// Class for setting up mocks and common test data which is used as fixture in tests
StreamImpl kDefaultStream_{};
}
} // namespace fixture
然后,打哈欠,到
class StreamImpl {
...
template <typename Type>
StreamImpl &operator<<(T &&out) noexcept;
...
};
// Templates implementation needed for test purposes
#include "StreamImpl.hpp"
#include "MockStreamImpl.hpp"
using ::utils::Dispatcher;
using ::mock::MockStreamImpl; // Error here
template <typename Type>
StreamImpl &operator<<(T &&out) noexcept
{
return Dispatcher<MockStreamImpl>::Instance().Get()->OutOperator(out);
}
namespace mock {
using ::StreamImpl;
class MockStreamImpl {
MOCK_METHOD(...); // Gmock methods
};
} // namespace mock
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;
class UtStream : public Test {
// Class for setting up mocks and common test data which is used as fixture in tests
StreamImpl kDefaultStream_{};
}
} // namespace fixture
并且由于 StreamImpl.hpp 和 MockStreamImpl.hpp 受到包含守衛的保護,我們得到
class StreamImpl {
...
template <typename Type>
StreamImpl &operator<<(T &&out) noexcept;
...
};
// Templates implementation needed for test purposes
using ::utils::Dispatcher;
using ::mock::MockStreamImpl; // Error here
template <typename Type>
StreamImpl &operator<<(T &&out) noexcept
{
return Dispatcher<MockStreamImpl>::Instance().Get()->OutOperator(out);
}
namespace mock { //because mock isn't found by the compiler until here
using ::StreamImpl;
class MockStreamImpl {
MOCK_METHOD(...); // Gmock methods
};
} // namespace mock
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;
class UtStream : public Test {
// Class for setting up mocks and common test data which is used as fixture in tests
StreamImpl kDefaultStream_{};
}
} // namespace fixture
我們可以看到MockStreamImpl它在定義之前是必需的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/418484.html
標籤:
