Я создал интерфейс (вот пример):
class DataStream
{
virtual std::string read(std::string terminator) = 0;
virtual size_t write(std::string data) = 0;
};
, для которого существует конкретная реализация, например:
class SerialDataStream : public DataStream
{
public:
// NOTE: This constructor will throw an exception if the
// serial port cannot be opened.
SerialDataStream(string port, int baudrate);
std::string read(std::string terminator);
size_t write(std::string data);
}
И интерфейс используется дляпример:
class SomeThing
{
public:
SomeThing(std::shared_ptr<DataStream> stream);
}
Используя GoogleMock, тестирование класса SomeThing довольно простое, все, что вам нужно сделать, это создать фиктивную реализацию для интерфейса, например:
class MockDataStream : public DataStream
{
public:
MOCK_METHOD1(read, size_t(std::vector<uint8_t>&));
MOCK_METHOD1(write, size_t(std::vector<uint8_t>&));
}
Гдетест выглядел бы примерно так:
std::shared_ptr<MockDataStream> mock_stream(nullptr);
mock_stream = std::make_shared<MockDataStream>();
EXPECT_CALL(*mock_stream, write("START")).Times(AtLeast(1));
EXPECT_CALL(*mock_stream, read("\n")).Times(AtLeast(1));
SomeThing some_thing = SomeThing(mock_stream);
Это довольно круто, так как легко позволяет мне протестировать, как класс SomeThing использует интерфейс DataStream.
Однако также существует некоторый кодчья работа заключается в создании новых (конкретных) объектов DataStream, и я обнаружил, что с помощью GoogleMock это немного сложнее проверить.Например, вот фрагмент кода, который нужно протестировать:
std::shared_ptr<DataStream> datastream(nullptr);
// Try and open the serial port:
try
{
std::shared_ptr<SerialDataStream> serialstream =
std::make_shared<SerialDataStream>("/dev/tty99", 115200);
}
catch (...)
{
// Returns a nullptr
return datastream;
}
// Check if there is a known device on the other end:
datastream = std::static_pointer_cast<DataStream>(serialstream);
if (!device_is_connected(datastream))
{
datastream = nullptr;
}
return datastream;
Я изо всех сил пытаюсь найти эффективный метод для тестирования этого кода с помощью GoogleMock:
- Я хотел бы посмеяться над конструктором (SerialDataStream), чтобы он выдавал исключение, и путь ошибки выполнялся, как и ожидалось.
- Я хотел бы проверить успешный путь, где частный API "device_is_connected" использует недавно созданныйобъект datastream.
Это тот случай, когда у меня нет другого выбора, кроме как создать ложную реализацию SerialDataStream и использовать внедрение зависимостей для проверки кода, который создает конкретные объекты DataStream?
Еслив этом случае мне просто нужно сделать API-интерфейс «device_is_connected» открытым, чтобы я мог просто протестировать его с помощью фиктивной реализации интерфейса (как указано выше) для тестирования, например:
datastream.write("DISCOVER");
string response = datastream.read("\n");
if (discovery_ok(response))
{
// do stuff
}
Я почти уверен, что ответил на свой вопрос и у меня не будет другого выбора, кроме как подделать класс SerialDataStream и использовать зависимостьХорошая инъекция, сделайте частные API публичными и просто протестируйте их через GoogleMock, но я открыт для предложений, если есть лучший способ, которым я мог бы / должен делать что-то здесь.