Google Mock - как вернуть другое значение, используя EXPECT_CALL для выхода из цикла - PullRequest
1 голос
/ 01 мая 2019

С помощью Google Mock, как мне указать EXPECT_CALL с возвращаемым значением N раз, а затем другим значением N + 1?

Единственный способ пройти тест - это указать вручную каждую итерацию, например:

EXPECT_CALL(mock, Read(address)).Times(5)
.WillOnce(Return(0))
.WillOnce(Return(0))
.WillOnce(Return(0))
.WillOnce(Return(0))
.WillOnce(Return(1));

Описание теста

Код подtest использует слово состояния, чтобы определить, следует ли завершить чтение данных цикла.EXPECT_CALL должен установить ожидание возврата 1 из проверенного метода Read () N раз, а в N-м цикле - 0, чтобы указать, что больше нет данных.

К сожалению, рассматриваемый код находится на отдельной машине, но вот типичный пример.

const unsigned int statusAddress = 0;
const unsigned int dataAddress   = 1;
const unsigned int maxData       = 8;

unsigned int dataBuffer[maxData] = {0};
int readIndex = 0;

// Check if data is available (read returns 1). 
unsigned int dataIsAvailable = Read(statusAddress);

// Keep reading data until no more is available or the buffer is full.
while ((dataIsAvailable == 1) && (readIndex < maxData))
{
    // Read data word.
    dataBuffer[readIndex++] = Read(dataAddress);

    // Read status to determine if more data is available.
    dataIsAvailable = Read(statusAddress);
}

Метод чтения является ложным.

Если я добавляю ожидания по порядку,последний EXPECT_CALL используется (я предполагаю, что WillOnce перезаписывает WillRepeatedly в коде Google).Очевидно, я неправильно понимаю, как упорядочено несколько EXPECT_CALL.

EXPECT_CALL(mock, Read(address)).Times(4).WillRepeatedly(Return(1));
EXPECT_CALL(mock, Read(address)).Times(1).WillOnce(Return(0));
Expected: to be called 4 times
 Actual: never called - unsatisfied and active

Поскольку нет никакого метода ...

WillN(Return(1), 4)

... Я предполагаю, что есть менее фиксированный способструктурирование EXPECT_CALL для более сложных и / или более длинных последовательностей данных?

Ответы [ 2 ]

0 голосов
/ 13 мая 2019

Существует простое решение вашей проблемы.Создайте экземпляр InSequence перед вашими ожиданиями.Это гарантирует, что письменные ожидания вызываются в том же порядке.

InSequence s;
EXPECT_CALL(mock, Read(address)).Times(4).WillRepeatedly(Return(1));
EXPECT_CALL(mock, Read(address)).Times(1).WillOnce(Return(0));

Дополнительная информация: нажмите

0 голосов
/ 02 мая 2019

Возможно, вы захотите посмотреть шаблон Делегирование вызовов на подделку для этого типа теста.

Я думаю, что если бы мне нужно было реализовать набор тестов, связанных с чтением различных потоков данных, я, вероятно, написал бы гибридный класс Mock / Fake, который позволял бы мне контролировать реальный поток, который должен быть прочитан. Например:

// Example reader class to be tested
class Reader
{
public:
    static const unsigned int statusAddress = 0;
    static const unsigned int dataAddress   = 1;
    static const unsigned int maxData       = 8;

    // Returns data sequence that was read
    vector<unsigned int> ReadFromDevice()
    {
        // Stream-reading code from your example goes here
    }

    virtual unsigned int Read(unsigned int address)
    {
        // Read from address code here
    }
};

// Mock reader class with some faking ability
class MockReader : public Reader
{
public:
    // Set up normal mock definition
    MOCK_METHOD1(Read, unsigned int(unsigned int address));

    // Optionally enable use of delegation to fake method
    void EnableFakeReader()
    {
        ON_CALL(*this, Read(_))
            .WillByDefault(Invoke(this, &MockReader::FakeRead));
    }

    // Set up a fake data sequence to be returned by Read()
    void SetFakeData(const vector<unsigned int> &data)
    {
        m_fakeData = data;
        m_fakeDataIndex = 0;
        EnableFakeReader();
    }

    // Read from fake data sequence
    unsigned int FakeRead(unsigned int address)
    {
        if (address == statusAddress)
            return m_fakeDataIndex < m_fakeData.size() ? 1 : 0;
        if (address == dataAddress)
            if (m_fakeDataIndex < m_fakeData.size())
                return m_fakeData[m_fakeDataIndex++];
        return 0;
    }

    vector<unsigned int> m_fakeData;
    size_t m_fakeDataIndex = 0;
};

TEST(ReaderTests, Test1)
{
    // Set up a fake data sequence to be read
    vector<unsigned int> testData ={ 1,2,3,4,5,6,7,8 };
    MockReader mock;
    mock.SetFakeData(testData);

    // Set any desired expectations about mocked functions
    EXPECT_CALL(mock, Read(Reader::statusAddress)).Times(9);
    EXPECT_CALL(mock, Read(Reader::dataAddress)).Times(8);

    // Data read should be the same as the test data
    EXPECT_EQ(testData, mock.ReadFromDevice());
}

Обратите внимание, что этот пример не соответствует шаблону поваренной книги Google Mock, указанному выше. Полный шаблон кулинарной книги позволит вам создать класс FakeReader и MockReader. MockReader будет владельцем и делегированием частного экземпляра класса FakeReader.

Вы также можете рассмотреть возможность помещения подделки в класс приспособлений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...