Этим летом у меня была точно такая же проблема.
У меня был пользовательский класс Socket
, и я хотел проверить, что произойдет, если read
или write
сгенерируют исключение. Я действительно хотел имитировать фреймворки Java, и сделал это так:
Я унаследовал класс Socket
в класс FakeSocket
и создал нечто под названием SocketExpectation
. Затем в модульных тестах я создал поддельные сокеты, настроил ожидания и затем передал этот поддельный сокет к коду, который я хотел протестировать.
У FakeSocket
были следующие методы (без лишних деталей):
uint32_t write(buffer, length); // calls check
uint32_t read(buffer, length); // calls check
bool matches();
void expect(expectation);
uint32_t check(CallType, buffer, length) const;
Они все довольно прямолинейны. check
проверяет аргументы на соответствие текущему ожиданию и, если все соответствует плану, переходит к выполнению требования SocketExpectation
.
У SocketExpectation
есть этот контур (также разделенный):
typedef enum { write, read } CallType;
SocketExpectation(CallType type);
SocketExpectation &with_arguments(void *a1, uint32_t a2); // expects these args
SocketExpectation &will_return(uint32_t value);
SocketExpectation &will_throw(const char * e); // test error handling
bool matches();
Я добавил больше методов по мере необходимости. Я хотел бы создать его следующим образом, а затем передать поддельный сокет соответствующему методу:
fake_socket = FakeSocket();
fake_socket.expect(SocketExpectation(write).with_arguments(....).will_return(...));
fake_socket.expect(SocketExpectation(read).with_arguments(...).will_throw("something"));