在 c++++ 中模擬外部依賴項(xiàng)有三種方法:1. 樁(預(yù)定義行為),2. 存根(記錄調(diào)用),3. 注入(作為參數(shù)傳遞模擬)。通過樁、存根和注入,可以隔離組件并創(chuàng)建健壯的單元測(cè)試。
C++ 單元測(cè)試中如何模擬外部依賴項(xiàng)
在單元測(cè)試中,模擬外部依賴項(xiàng)對(duì)于隔離各個(gè)組件的測(cè)試非常重要。以下三種方法可以在 C++ 中輕松模擬外部依賴項(xiàng):
1. 樁(Stub)
樁是一種模擬,它提供預(yù)先定義的行為,而不會(huì)調(diào)用實(shí)際的依賴項(xiàng)。要?jiǎng)?chuàng)建樁,可以使用嘲諷框架,例如 Google Mock 或 CMocka。
// 使用 Google Mock 創(chuàng)建一個(gè)樁: class MockExternalDependency { public: MOCK_METHOD(int, Function1, (int a, int b)); }; // 創(chuàng)建樁并用它替換實(shí)際的依賴項(xiàng): MockExternalDependency mockDependency; EXPECT_CALL(mockDependency, Function1(1, 2)).WillOnce(Return(3)); // 測(cè)試代碼: int result = TestFunction(&mockDependency); ASSERT_EQ(result, 3);
登錄后復(fù)制
2. 存根(Stub)
存根與樁類似,但它不會(huì)預(yù)先定義行為。相反,它會(huì)記錄依賴項(xiàng)的調(diào)用并允許您檢查它們。這對(duì)于檢查輸入和調(diào)用順序非常有用。
// 使用 CMocka 創(chuàng)建一個(gè)存根: void external_dependency_stub(int a, int b) { // 記錄被調(diào)用的參數(shù) } // 設(shè)置存根并測(cè)試代碼: cmocka_set_stub(external_dependency, external_dependency_stub); TestFunction(); // 檢查存根中記錄的調(diào)用: ASSERT_TRUE(cmocka_call_count(external_dependency) > 0);
登錄后復(fù)制
3. 注入
注入涉及將依賴項(xiàng)作為參數(shù)傳遞給被測(cè)試函數(shù)。這允許您輕松地替換依賴項(xiàng)的實(shí)現(xiàn),以便在測(cè)試期間使用模擬。
// 使用依賴項(xiàng)注入進(jìn)行測(cè)試: void TestFunction(ExternalDependency& dependency) { // 使用模擬依賴項(xiàng)調(diào)用函數(shù): MockExternalDependency mockDependency; EXPECT_CALL(mockDependency, Function1(1, 2)).WillOnce(Return(3)); int result = TestFunction(&mockDependency); ASSERT_EQ(result, 3); }
登錄后復(fù)制
實(shí)戰(zhàn)案例:
假設(shè)我們有一個(gè)函數(shù) ReadFile
,它依賴于外部類 FileSystem
中的 OpenFile
和 ReadFile
方法。為了對(duì) ReadFile
進(jìn)行單元測(cè)試,我們需要模擬 FileSystem
:
class MockFileSystem { public: MOCK_METHOD(FILE*, OpenFile, (const char* filepath)); MOCK_METHOD(int, ReadFile, (FILE* file, char* buffer, int size)); }; void TestReadFile() { MockFileSystem mockFileSystem; FILE* mockFile = fopen("mockfile.txt", "w"); EXPECT_CALL(mockFileSystem, OpenFile("mockfile.txt")).WillOnce(Return(mockFile)); EXPECT_CALL(mockFileSystem, ReadFile(mockFile, testing::_, _)) .WillOnce(SetArrayArgument<1>("Hello", 5)); char buffer[10]; int result = ReadFile("mockfile.txt", buffer, 10, &mockFileSystem); ASSERT_EQ(result, 5); ASSERT_STREQ(buffer, "Hello"); }
登錄后復(fù)制