Google тестирует локальную функцию, которая вызывает другую функцию

#c #googletest

Вопрос:

У меня есть класс, который я хочу протестировать.

 class Myclass {
      virtual int functionA (int x) {
          if (x==1) {
             functionB();
             return 1;
          }
          else return 0;
      }
      virtual void functionB() {
          // do some logic
          functionC();
          printf ("functionB n"};
      }
      virtual void functionC() {
          // do some logic
          printf ("functionC n"};
      }
}
 

Я создал макет класса:

 
    class MockMyClass : public Myclass {
          MOCKMETHOD1(functionA, int(int x));
          MOCKMETHOD0(functionB, void());
          MOCKMETHOD0(functionC, void());
    }

 

Мой тестовый случай в тестовом классе:

 
    class MyTesting : public testing::Test {
          virtual void SetUp(){
              testObj = new MyClass();
              testMock = new MockMyClass();
          }
          virtual void Teardown() {
              delete testObj;
              delete testMock;
          }
    }
    MyClass * testObj;
    MockMyClass * testMock;
    TEST_F (MyClass, Test1){
        EXPECT_CALL (testMock, functionB());
        testObj->functionA() 
    }
    TEST_F (MyClass, Test2){
        EXPECT_CALL (testMock, functionC());
        testObj->functionB() 
    }
    TEST_F (MyClass, Test3){
        EXPECT_CALL (testMock, functionC());
        testObj->functionC() 
    }

 

В принципе, мне нужно запустить функцию -> functionB ->> functionC.

Как можно написать Тест1 таким образом, чтобы при ожидаемом вызове функции B он не «шел дальше» в B и требовал другого ожидаемого вызова функции C.

Другими словами, как можно написать Test1 таким образом, чтобы любая логика в functionB была протестирована в Test2 и далее в Test3 и Test1, просто ожидайте вызова functionB.

Ответ №1:

 TEST_F (MyClass, Test1) {
    InSequence seq;
    EXPECT_CALL (MockMyClass, functionB());
    EXPECT_CALL (MockMyClass, functionC());
    testObj->functionA(1);
}
 

Непоследовательность

Ваш пример не будет компилироваться, для функции требуется arg и пропущенные точки с запятой.

Комментарии:

1. Я думаю, что у меня с этим проблема. Тест завершается неудачно из-за ошибки: «Фактическое количество вызовов функций не соответствует ожидаемому вызову». Я думаю, что functionB и functionC вызываются одним и тем же объектом, который вызывает функцию,. Таким образом, когда я помещаю туда «MockMyClass», это не работает.

2. Пожалуйста, позаботьтесь о том, чтобы ваш пример был составлен. Слишком много ошибок. После того, как вы его скомпилируете, я покажу вам рабочий пример.

Ответ №2:

Главная проблема здесь-неправильное использование наследования.

Если ваш тестируемый класс такой же, как макет класса, то должно быть очевидно, что здесь что-то не так.

Обратите внимание, что здесь:

 virtual void SetUp() {
    testObj = new MyClass();
    testMock = new MockMyClass();
}
 

нет никакой зависимости между testObj и testMock . Итак, вопрос в том, как testObje это может повлиять на состояние testMock ? Этого не может быть!

Таким образом, в основном проблема заключается в разработке вашего кода производственного кода (тестируемого кода).

Поскольку логика этого класса была запутана, у меня нет никаких подсказок, как я мог бы правильно исправить ваш код. Я предполагаю, что это должно быть что-то вроде этого:

 class ISomeDependency {
public:
    virtual int functionA(int x) = 0;
};

//---------

class Myclass {
public:
    Myclass(ISomeDependencyamp; dep)
        : mDep { dep }
    {
    }

    void functionB()
    {
        if (mDep.function(1) > 5) {
            functionC();
        }
    }
    void functionC()
    {
    }

private:
    ISomeDependencyamp; mDep;
};
 
 class MyclassTest : public ::testing::Test {

    void checkMyClassIsInStateX()
    {
        ASSERT_EQ(myClass.getX(), ...);
    }

public:
    MockSomeDependency mock;
    Myclass myClass { mock };
};

TEST_F(MyclassTest, functionBCallsDependencyWithOneAndChangesStateToX)
{
    EXPECT_CALL(mock, functionA(1)).WillOnce(Return(4));
    myClass.functionB();
    checkMyClassIsInStateX();
}