2017-02-20 4 views
2

У меня есть такая группа -> элемент для добавления/удаления, с кодом snippt:как ожидать аргумент указателя, который создается позже

// production code: 
Group::add(Element* e) {...}; 
Group::remove(Element* e) {...}; 
ElementDerived::ElementDerived(Group* group){ group->add(this);} 
ElementDerived::~ElementDerived(Group* group){ group->remove(this);} 

всякий раз, когда я хочу, чтобы проверить класс ElementDerived, я должен сделать следующее в настройке/отрыве. Однако, как я могу установить аргумент ожидания явно без _?

// test code: 
struct Test_ElementDerived : public ::testing::Test { 
    void SetUp() override { 
    ElementDerived* p = nullptr; 
    EXPECT_CALL(group, add(_)) // how to set expection on the pointer argument? 
     .WillOnce(Invoke([&p](auto base_ptr) { 
     p = static_cast<ElementDerived*>(base_ptr); 
     })); 
    sut = std::make_unique<ElementDerived>(&group); 
    } 
    void TearDown() override { 
    EXPECT_CALL(group, remove(sut.get())); 
    } 
    MockGroup group{}; 
    std::unique_ptr<ElementDerived> sut; 
}; 
+0

ОЖИДАНИЯ, вероятно, должны быть установлены в телах ТЕСТ, а не в приспособлении. –

+0

хорошо, я согласен, но это общее правило. в некоторых случаях действия уже выполняются с помощью конструктора. и вы видите фрагмент кода, это не сложный или необоснованный случай. – pepero

+0

'EXPECT_EQ (sut.get(), p);'? – Jarod42

ответ

0

Вы можете сделать это:

Element* p = nullptr; 
EXPECT_CALL(group, add(_)).WillOnce(SaveArg<0>(&p)); 
sut = std::make_unique<ElementDerived>(&group); 
ASSERT_EQ(p, static_cast<Element*>(sut.get())); 

Это не сильно отличается от того, что вы сделали. Для того, чтобы заменить _ с некоторой согласованью - вы должны знать указатель - единственный путь для достижения этой цели является использование размещения нового:

struct DestructCaller { 
    template <typename T> void operator()(T* ptr) 
    { 
     if (ptr) ptr->~T(); 
    } 
}; 
std::aligned_storage_t<sizeof(ElementDerived), alignof(ElementDerived)> sut_storage; 
std::unique_ptr<ElementDerived, DestructCaller> sut; 

void SetUp() override 
{ 

    EXPECT_CALL(group, add((ElementDerived*)&sut_storage)); 
    sut.reset(new (&sut_storage) ElementDerived(&group)); 
} 

Или подобной концепции с неограниченным союзом:

union 
{ 
    ElementDerived sut; 
}; 

void SetUp() override 
{ 

    EXPECT_CALL(group, add(&sut)); 
    new (&sut) ElementDerived(&group); 
} 
void TearDown() override 
{ 

    EXPECT_CALL(group, remove(&sut)); 
    sut.~ElementDerived(); 
} 

В моем личное мнение - путь с SaveArg и ASSERT_EQ более читабельен.

Смежные вопросы