#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();
}