1. 리턴 값을 강제로 지정하는 예제

 

class MockFoo : public Foo {
 public:
  MOCK_METHOD(int, GetSize, (), (const, override));
};

TEST(MyMockTest, ReturnsTest) {
  MockFoo mock_foo;
  ON_CALL(mock_foo, GetSize()).WillByDefault(Return(42));
  EXPECT_EQ(42, mock_foo.GetSize());
}

 

2. 입력 인자를 확인하는 예제

class MockFoo : public Foo {
 public:
  MOCK_METHOD(int, Add, (int x, int y), (override));
};

TEST(MyMockTest, ArgumentTest) {
  MockFoo mock_foo;
  EXPECT_CALL(mock_foo, Add(4, 5)).WillOnce(Return(9));
  EXPECT_EQ(9, mock_foo.Add(4, 5));
}

 

3. 입력 인자를 변경하는 예제

class MockFoo : public Foo {
 public:
  MOCK_METHOD(int, Sum, (int x, int y), (override));
};

TEST(MyMockTest, ArgumentChangeTest) {
  MockFoo mock_foo;
  int x = 2;
  int y = 3;
  EXPECT_CALL(mock_foo, Sum(_, _)).WillOnce(DoAll(
      SaveArg<0>(&x), SaveArg<1>(&y),
      Return(0)));
  mock_foo.Sum(1, 2);
  EXPECT_EQ(1, x);
  EXPECT_EQ(2, y);
}

 

4. 순서를 지정하는 예제

 

class MockFoo : public Foo {
 public:
  MOCK_METHOD(int, GetSize, (), (const, override));
  MOCK_METHOD(void, SetSize, (int size), (override));
};

TEST(MyMockTest, OrderTest) {
  MockFoo mock_foo;
  EXPECT_CALL(mock_foo, GetSize()).WillOnce(Return(42));
  EXPECT_CALL(mock_foo, SetSize(84)).After(
      EXPECT_CALL(mock_foo, GetSize()).WillOnce(Return(42)));
  mock_foo.GetSize();
  mock_foo.SetSize(84);
}

 

5. 예외를 던지는 예제

 

class MockFoo : public Foo {
 public:
  MOCK_METHOD(void, Func, (), (override));
};

TEST(MyMockTest, ExceptionTest) {
  MockFoo mock_foo;
  EXPECT_CALL(mock_foo, Func()).WillOnce(
      Throw(std::runtime_error("error")));
  EXPECT_THROW(mock_foo.Func(), std::runtime_error);
}

6. 특정 횟수만큼 호출하는 예제

 

class MockFoo : public Foo {
 public:
  MOCK_METHOD(void, Func, (), (override));
};

TEST(MyMockTest, TimesTest) {
  MockFoo mock_foo;
  EXPECT_CALL(mock_foo, Func()).Times(2);
  mock_foo.Func();
  mock_foo.Func();
}

7. 다른 함수를 호출하는 예제

class MockFoo : public Foo {
 public:
  MOCK_METHOD(void, Func1, (), (override));
  MOCK_METHOD(void, Func2, (), (override));
};

TEST(MyMockTest, CallOtherFunctionTest) {
  MockFoo mock_foo;
  EXPECT_CALL(mock_foo, Func1())
      .WillOnce(InvokeWithoutArgs([&mock_foo]() {
        mock_foo.Func2();
      }));
  EXPECT_CALL(mock_foo, Func2());
  mock_foo.Func1();
}

 

 

gmock test 예제

  1. 함수 인자 검증 (Argument Verification)
TEST(MathTest, DivideByZero) {
  MockFunction<double(double, double)> mock_divide;

  EXPECT_CALL(mock_divide, Call(10, 0))
      .WillOnce(Throw(std::runtime_error("Divide by zero")));

  Math math;
  EXPECT_THROW(math.Divide(10, 0, &mock_divide), std::runtime_error);
}

 

이 예제에서는 Math 클래스의 Divide 함수에서 인자로 받은 두 숫자를 나누는데, 만약 두 번째 인자가 0이면 std::runtime_error 예외를 던지도록 되어 있음

이 함수가 제대로 작동하는지 검증하기 위해서, MockFunction을 이용해 인자로 10과 0을 전달했을 때 std::runtime_error 예외를 던지는 것을 확인

 

2. 다수의 반환값 (Multiple Return Values)

 

class MockDatabase : public Database {
 public:
  MOCK_METHOD(std::string, LookupName, (int id), (override));

 private:
  std::map<int, std::string> id_to_name_ = {
      {1, "Alice"},
      {2, "Bob"},
      {3, "Charlie"},
      {4, "Dave"},
      {5, "Eve"},
  };
};

TEST(LookupTest, ReturnsNameForValidId) {
  MockDatabase mock_database;
  EXPECT_CALL(mock_database, LookupName(1))
      .WillOnce(Return("Alice"));

  NameLookup name_lookup(&mock_database);
  std::string name = name_lookup.GetName(1);
  ASSERT_EQ("Alice", name);
}

 

이 예제에서는 Database 클래스를 상속받은 MockDatabase 클래스를 이용해 특정 id에 해당하는 이름을 반환하는 LookupName 함수를 테스트

EXPECT_CALL을 이용해 1에 해당하는 이름이 "Alice"인 것을 확인

 

3.  구글 테스트와 같이 사용하기 (Integration with Google Test)

TEST_F(MyTest, TestConnection) {
  MockConnection conn;
  ON_CALL(conn, Connect())
      .WillByDefault(Return(true));
  ON_CALL(conn, Disconnect())
      .WillByDefault(Return(true));

  MyObject obj(&conn);

  EXPECT_TRUE(obj.IsConnected());
  obj.DoSomething();
  EXPECT_TRUE(obj.IsConnected());
  obj.DoSomethingElse();
  EXPECT_TRUE(obj.IsConnected());
}

이 예제에서는 MyObject 클래스가 MockConnection을 이용해 연결하는지 여부를 검증

ON_CALL을 이용해 Connect()Disconnect() 함수가 호출될 때 각각 true를 반환하도록 설정한 후,

MyObject 객체를 생성하여 IsConnected() 함수의 반환값이 true인지 여부를 확인

이 예제는 구글 테스트(Google Test)와 함께 사용될 때 많이 쓰임

 

 

예제

#include <iostream>
#include <string>
#include <vector>
#include "gmock/gmock.h"

using namespace std;
using namespace testing;

// 모의 클래스 정의
class MyMockClass {
public:
    MOCK_METHOD2(MyMethod, int(int arg1, const string& arg2));
};

// 테스트 클래스 정의
class MyTestClass : public Test {
public:
    void SetUp() override {
        // 모의 클래스 객체 생성
        my_mock_object_ = new MyMockClass;
        // 모의 클래스 객체와 함수 연결
        ON_CALL(*my_mock_object_, MyMethod(_, _))
            .WillByDefault(Return(0));
    }

    void TearDown() override {
        delete my_mock_object_;
    }

protected:
    MyMockClass* my_mock_object_;
};

// 테스트 케이스 1
TEST_F(MyTestClass, Test1) {
    // 모의 함수 호출
    EXPECT_CALL(*my_mock_object_, MyMethod(42, "Hello"))
        .WillOnce(Return(1));
    // 테스트
    ASSERT_EQ(my_mock_object_->MyMethod(42, "Hello"), 1);
}

// 테스트 케이스 2
TEST_F(MyTestClass, Test2) {
    // 모의 함수 호출
    EXPECT_CALL(*my_mock_object_, MyMethod(69, "World"))
        .WillOnce(Return(2));
    // 테스트
    ASSERT_EQ(my_mock_object_->MyMethod(69, "World"), 2);
}

// 테스트 케이스 3
TEST_F(MyTestClass, Test3) {
    // 모의 함수 호출
    EXPECT_CALL(*my_mock_object_, MyMethod(123, _))
        .WillOnce(Return(3));
    // 테스트
    ASSERT_EQ(my_mock_object_->MyMethod(123, "Whatever"), 3);
}

// 테스트 케이스 4
TEST_F(MyTestClass, Test4) {
    // 모의 함수 호출
    vector<pair<int, string>> args = {{1, "a"}, {2, "b"}, {3, "c"}};
    vector<int> ret_vals = {4, 5, 6};
    EXPECT_CALL(*my_mock_object_, MyMethod(_, _))
        .WillOnce(Return(ret_vals[0]))
        .WillOnce(Return(ret_vals[1]))
        .WillOnce(Return(ret_vals[2]));
    // 테스트
    for (size_t i = 0; i < args.size(); ++i) {
        ASSERT_EQ(my_mock_object_->MyMethod(args[i].first, args[i].second), ret_vals[i]);
    }
}

// 테스트 케이스 5
TEST_F(MyTestClass, Test5) {
    // 모의 함수 호출
    EXPECT_CALL(*my_mock_object_, MyMethod(_, _))
        .WillOnce(Return(1));
    // 테스트
    ASSERT_EQ(my_mock_object_->MyMethod(42, "Hello"), 1);
    ASSERT_EQ(my_mock_object_->MyMethod(69, "World"), 1);
}

int main(int argc, char** argv) {
    InitGoogleMock(&argc, argv);
    return RUN_ALL_TESTS();
}


예제3

class Bank {
public:
    virtual ~Bank() {}
    virtual void deposit(int amount) = 0;
};
class Customer {
public:
    Customer(Bank* bank) : bank_(bank) {}

    void deposit(int amount) {
        if (amount <= 0) {
            throw std::runtime_error("Invalid amount");
        }
        bank_->deposit(amount);
    }

private:
    Bank* bank_;
};

Customer 클래스는 다음과 같이 Bank 클래스를 멤버로 가지고 있음

'

 

Customer 객체가 Bank 객체의 deposit 메서드를 호출할 때, 다양한 오류 상황이 발생할 수 있음

이를 gmock을 활용해서 검증

 

먼저, Bank 클래스를 mocking

class MockBank : public Bank {
public:
    MOCK_METHOD(void, deposit, (int amount), (override));
};

 

다음으로, Customer 클래스의 deposit 메서드가 예상한 대로 작동하는지 검증해봅니다. 이때, Bank 클래스의 deposit 메서드를 호출할 때, 어떤 인자가 전달되는지에 대한 검증도 수행

 

TEST(CustomerTest, DepositSuccess) {
    MockBank bank;
    Customer customer(&bank);

    EXPECT_CALL(bank, deposit(100));

    customer.deposit(100);
}

 

이번에는 Customer 객체가 deposit 메서드를 호출할 때, 음수 값을 전달하는 경우가 발생하는지 검증해보겠습니다. 이를 위해서는 Bank 객체의 deposit 메서드가 호출되지 않아야 합니다

 

TEST(CustomerTest, DepositWithNegativeAmount) {
    MockBank bank;
    Customer customer(&bank);

    EXPECT_THROW(customer.deposit(-100), std::runtime_error);
    EXPECT_CALL(bank, deposit(_)).Times(0);
}

 

마지막으로, Bank 객체의 deposit 메서드에서 예외가 발생하는 경우도 검증해봅니다. 이를 위해서는 Customer 객체가 Bank 객체의 deposit 메서드를 호출할 때, 예외가 발생할 것임을 미리 알고 있어야 합니다.

 

TEST(CustomerTest, DepositThrowsException) {
    MockBank bank;
    Customer customer(&bank);

    EXPECT_CALL(bank, deposit(100)).WillOnce(
        [] (int amount) { throw std::runtime_error("Failed to deposit"); });

    EXPECT_THROW(customer.deposit(100), std::runtime_error);
}

위 예제에서는 gmock을 활용해서 Customer 객체가 Bank 객체의 deposit 메서드를 호출할 때, 발생할 수 있는 다양한 오류 상황을 검증

 

 

설명

 

  • 어떤 프로그램이 Customer 객체를 생성합니다.
  • Customer 객체는 Bank 객체에 대한 참조자를 가지고 있습니다.
  • Customer 객체의 makeDeposit 메서드를 호출하면, Bank 객체의 deposit 메서드가 호출되어야 합니다.
  • Bank 객체의 deposit 메서드는 인자로 받은 금액을 해당 계좌에 입금합니다.
  • 이때, Bank 객체가 인증되지 않은 경우에는 입금이 되지 않아야 합니다.

위의 상황을 검증하기 위해서는 다음과 같은 동작이 필요합니다.

  1. Bank 객체를 모의(mock)합니다.
  2. Bank 객체를 모의하면서, deposit 메서드가 호출될 때 인자로 넘어오는 값을 검증할 수 있도록 합니다.
  3. Bank 객체를 모의하면서, deposit 메서드가 호출되기 전에 먼저 인증 과정을 거쳐야 한다는 것을 검증할 수 있도록 합니다.
  4. Customer 객체를 생성합니다. 이때, 모의된 Bank 객체의 참조자를 Customer 객체에 전달합니다.
  5. Customer 객체의 makeDeposit 메서드를 호출합니다. 이때, 모의된 Bank 객체의 deposit 메서드가 호출되어야 합니다.
  6. 모의된 Bank 객체에서 deposit 메서드의 인자로 넘어온 값을 검증합니다.
  7. 모의된 Bank 객체에서 인증 과정이 올바르게 진행되었는지 검증합니다.

이렇게 하면, Customer 객체가 Bank 객체의 deposit 메서드를 호출할 때 발생할 수 있는 다양한 오류 상황을 검증할 수 있습니다. 이를 위해서 gmock을 사용하면, 모의 객체를 쉽게 생성하고 다양한 동작을 검증할 수 있습니

'유닛 테스트(unit test)' 카테고리의 다른 글

[C++] google test - gmock #1  (0) 2023.03.24

unit test 란

 

 

 

mocking 이란

mocking은 유닛 테스트에서 사용되는 기술 중 하나로, 의존성 있는 코드를 테스트할 때, 해당 의존성을 가짜 객체로 대체하여 테스트하는 것을 의미함

즉, 의존성 있는 코드를 호출할 때, 그 코드가 호출하는 객체를 대신해서 가짜 객체를 사용하여 호출하는 것

이 가짜 객체는 실제 객체와 동일한 인터페이스를 제공하지만, 미리 정의된 테스트 케이스에 따라서 적절한 결과를 반환

이렇게 하면 의존성이 있는 코드의 결과를 예측 가능하게 만들어

또한, 의존성이 있는 코드를 모의(mock) 객체로 대체하면, 해당 객체가 실제 시스템에 영향을 미치지 않고도 코드를 테스트할 수 있음

 

 

Queue라는 클래스가 있다고 가정하고, Queue가 의존하는 클래스인 Data라는 클래스를 mocking하는 예제

// Queue.h
#include "Data.h"

class Queue {
public:
    Queue(Data* data);
    int size();
private:
    Data* data_;
};

// Queue.cpp
#include "Queue.h"

Queue::Queue(Data* data) : data_(data) {}

int Queue::size() {
    return data_->getSize();
}

// MockData.h
#include "Data.h"
#include "gmock/gmock.h"

class MockData : public Data {
public:
    MOCK_METHOD(int, getSize, (), (override));
};

// QueueTest.cpp
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "Queue.h"
#include "MockData.h"

using ::testing::Return;

TEST(QueueTest, SizeTest) {
    MockData mock_data;
    Queue q(&mock_data);
    EXPECT_CALL(mock_data, getSize()).WillOnce(Return(3));
    ASSERT_EQ(q.size(), 3);
}

 

이 예제에서는 Queue 클래스가 Data 클래스에 의존하고 있음

그리고 QueueTest에서는 Queue의 size() 메소드를 테스트하고자 함

하지만, size() 메소드는 Data의 getSize() 메소드를 호출하기 때문에, Data 클래스에 의존하고 있는 상황

이를 해결하기 위해 MockData 클래스를 만들어 Data 클래스를 mocking

 

Queue 클래스에서는 생성자에서 Data 객체를 받아서 멤버 변수로 저장

size() 메소드에서는 Data 객체의 getSize() 메소드를 호출하여 반환값을 리턴

QueueTest에서는 MockData 객체를 생성하고, Queue 객체를 생성할 때 이를 전달

그리고 EXPECT_CALL 매크로를 사용하여, MockData 객체의 getSize() 메소드가 호출될 때 3을 반환하도록 지정

마지막으로 ASSERT_EQ 매크로를 사용하여 Queue 객체의 size() 메소드가 3을 반환하는지 확인

이렇게 Mocking을 통해, Queue 클래스가 Data 클래스에 의존하는 상황에서도 테스트를 수행할 수 있게됨

 

 

mocking을 사용하여 실제 데이터베이스에 접근하지 않고 데이터베이스를 대체하는 예제

 

예를 들어, 데이터베이스에서 사용자 정보를 가져와 로그인 인증을 수행하는 함수가 있는데,

이 함수는 데이터베이스에 직접 연결하여 쿼리를 실행하므로 테스트를 수행하는 데 시간이 많이 소요된다고 가정

이런 경우 mocking을 사용하여 데이터베이스에 연결하지 않고도 테스트를 수행할 수 있음

 

먼저 사용자 정보를 나타내는 User 클래스는 아래 처럼 디자인 해볼 수 있음

class User {
public:
    User(const std::string& name, const std::string& password) : name_(name), password_(password) {}
    const std::string& GetName() const { return name_; }
    const std::string& GetPassword() const { return password_; }
private:
    std::string name_;
    std::string password_;
};

 

데이터베이스와 상호작용하는 UserRepository 클래스

class UserRepository {
public:
    std::shared_ptr<User> GetUserByName(const std::string& name) {
        // 데이터베이스에 연결하여 쿼리 실행
        // ...
        // 결과를 User 객체로 변환하여 반환
        return std::make_shared<User>(name, "password");
    }
};
 
UserRepository를 사용하여 로그인 인증을 수행하는 LoginService 클래스
 
class LoginService {
public:
    bool Authenticate(const std::string& name, const std::string& password) {
        UserRepository repository;
        std::shared_ptr<User> user = repository.GetUserByName(name);
        if (!user) {
            return false;
        }
        return user->GetPassword() == password;
    }
};

 

이제 LoginService의 Authenticate 함수를 테스트하려면 UserRepository 클래스의 GetUserByName 함수를 호출해야 함

그러나 이 함수는 데이터베이스에 직접 연결하기 때문에 테스트하는 데 시간이 많이 소요됨

따라서 mocking을 사용하여 UserRepository 클래스의 GetUserByName 함수를 대체할 수 있음

 

이를 위해 UserRepository 클래스를 인터페이스로 추상화하고, 이 인터페이스를 상속하는 MockUserRepository 클래스를 작성

class IUserRepository {
public:
    virtual std::shared_ptr<User> GetUserByName(const std::string& name) = 0;
};

class MockUserRepository : public IUserRepository {
public:
    MOCK_METHOD1(GetUserByName, std::shared_ptr<User>(const std::string& name));
};

 

여기서 MOCK_METHOD1 매크로는 IUserRepository 클래스의 GetUserByName 함수를 대체하기 위한 mocking 함수를 생성

이제 LoginService 클래스의 Authenticate 함수를 테스트하려면 MockUserRepository 클래스의 GetUserByName 함수를 호출

 

TEST(LoginServiceTest, TestAuthenticate) {
    // Mocking을 사용하여 UserRepository 대체
    MockUserRepository repository;
    LoginService service;

    // mocking 함수 설정
    EXPECT_CALL(repository, GetUserByName("Alice"))

 

 

  1. Mocking with multiple dependencies (다수의 의존성을 가진 클래스에 대해 mocking을 수행하는 예제)

아래 코드에서는 ClassA와 ClassB 두 개의 클래스가 ClassC에서 의존성으로 사용되며,

ClassC의 테스트를 위해 ClassA와 ClassB를 mocking 

class ClassA {
public:
  virtual void funcA() = 0;
};

class ClassB {
public:
  virtual void funcB() = 0;
};

class ClassC {
public:
  ClassC(std::shared_ptr<ClassA> a, std::shared_ptr<ClassB> b) 
    : a_(a), b_(b) {}

  void funcC() {
    a_->funcA();
    b_->funcB();
  }

private:
  std::shared_ptr<ClassA> a_;
  std::shared_ptr<ClassB> b_;
};

TEST(ClassCTest, TestFuncC) {
  // Mock ClassA and ClassB
  auto mockA = std::make_shared<MockClassA>();
  auto mockB = std::make_shared<MockClassB>();

  // Set expectations
  EXPECT_CALL(*mockA, funcA());
  EXPECT_CALL(*mockB, funcB());

  // Inject mocks into ClassC
  ClassC c(mockA, mockB);

  // Test ClassC's funcC
  c.funcC();
}

 

 

2. Mocking with non-virtual interface (가상 함수가 아닌 인터페이스를 사용하는 클래스에 대해 mocking을 수행하는 예제)

 

아래 코드에서는 ClassD가 ClassE를 의존성으로 사용하며, ClassD를 mocking

ClassD는 인터페이스인 ID를 구현하며, ClassE는 ID를 통해 ClassD와 상호작용함

class ID {
public:
  virtual void funcD() = 0;
};

class ClassD : public ID {
public:
  void funcD() override {
    funcE();
  }

  virtual void funcE() {
    // implementation
  }
};

class ClassE {
public:
  ClassE(ID& d) : d_(d) {}

  void funcE() {
    d_.funcD();
  }

private:
  ID& d_;
};

class MockClassD : public ID {
public:
  MOCK_METHOD(void, funcD, (), (override));
};

TEST(ClassETest, TestFuncE) {
  // Mock ClassD
  MockClassD mockD;

  // Set expectations
  EXPECT_CALL(mockD, funcD());

  // Create ClassE with mockD
  ClassE e(mockD);

  // Test ClassE's funcE
  e.funcE();
}

 

 

3. Partial Mocking (Partial Mocking을 사용하여 클래스의 일부 함수만 mocking 하는 예제)

아래 코드에서는 ClassF가 funcF와 funcG 함수를 가지며, funcF를 mocking 

funcG 함수는 실제로 호출되며, ClassF의 인스턴스는 Partial Mocking이 적용

 

class ClassF {
public:
  virtual void funcF() {
    // implementation
  }

  void funcG() {
    // implementation
  }
};

TEST(ClassFTest, TestFuncF) {

 

 

+ QNX 에서  WillOnce 사용 불가.

 

이 경우에는 대신 OnCall 함수를 사용하여 함수 호출 시점에서 특정 값을 반환하도록 설정

 

class MyClass {
public:
    virtual int GetValue() const { return 0; }
};

class MyMock : public MyClass {
public:
    MOCK_CONST_METHOD0(GetValue, int());
};

 

MyMock 클래스에서 GetValue() 함수를 mock으로 설정하고,

WillOnce 함수를 사용하여 값을 반환하는 것 대신,

OnCall 함수를 사용하여 특정 값을 반환하도록 설정할 수 있습니다.

 

즉  다음과 같은 방법으로 설정할 수 있음

MyMock mock;
EXPECT_CALL(mock, GetValue())
    .WillOnce(Invoke([&]() {
        // OnCall 대신에 직접 처리하면 됩니다.
        return 42;
    }));

이제 MyMockGetValue() 함수가 호출되면, 42를 반환하도록 설정되어 있음

이렇게 하면 WillOnce 함수를 사용할 수 없는 환경에서도 유용한 방법으로 mocking을 구현할 수 있음

 

 

예제2

#include <iostream>
#include <memory>

class IDataReader {
public:
    virtual ~IDataReader() = default;
    virtual int ReadData(char* buffer, int size) = 0;
};

class MockDataReader : public IDataReader {
public:
    MOCK_METHOD(int, ReadData, (char* buffer, int size), (override));
};

class DataProcessor {
public:
    explicit DataProcessor(std::shared_ptr<IDataReader> reader) : reader_(std::move(reader)) {}

    bool ProcessData() {
        char buffer[1024];
        int bytes_read = reader_->ReadData(buffer, sizeof(buffer));

        if (bytes_read < 0) {
            std::cerr << "Error reading data" << std::endl;
            return false;
        }

        // process the data...

        return true;
    }

private:
    std::shared_ptr<IDataReader> reader_;
};

class MockDataReaderWrapper : public IDataReader {
public:
    MockDataReaderWrapper(MockDataReader& mock_reader) : mock_reader_(mock_reader) {}

    int ReadData(char* buffer, int size) override {
        return mock_reader_.ReadData(buffer, size);
    }

private:
    MockDataReader& mock_reader_;
};

TEST(DataProcessorTest, ProcessDataTest) {
    MockDataReader mock_reader;
    MockDataReaderWrapper mock_reader_wrapper(mock_reader);
    DataProcessor processor(std::make_shared<MockDataReaderWrapper>(mock_reader_wrapper));

    EXPECT_CALL(mock_reader, ReadData(_, _)).WillOnce(Return(10));

    ASSERT_TRUE(processor.ProcessData());
}

이 예제에서는 IDataReader라는 인터페이스를 정의하고, 이를 구현하는 MockDataReader 클래스를 만들었음

그리고 DataProcessor 클래스는 IDataReader 객체를 인자로 받아 데이터를 처리함

 

위 예제에서는 WillOnce 함수 대신 MockDataReaderWrapper 클래스를 만들어 사용

MockDataReaderWrapper 클래스는 IDataReader 인터페이스를 구현하면서, 내부적으로 MockDataReader 객체를 참조 DataProcessor 클래스에서는 std::shared_ptr<IDataReader> 타입으로 MockDataReaderWrapper 객체를 받아 처리

마지막으로 EXPECT_CALL 매크로를 사용하여 MockDataReader 클래스의 ReadData 함수가 호출될 때 반환 값을 지정

이 때 ReadData 함수는 MockDataReaderWrapper 클래스를 통해 호출됨

이 예제에서는 MockDataReaderWrapper 클래스를 사용하여 QNX 환경에서 WillOnce 함수를 대체할 수 있음

 

 

'유닛 테스트(unit test)' 카테고리의 다른 글

[C++] google test - gmock #2  (0) 2023.03.25

+ Recent posts