我面临着一种情况,我们在代表 HTTP 会话的类内部使用
http::async_read(...)
和 http::async_write(...)
。但是,如果我们想对此类进行单元测试,我们不希望打开网络连接,而是使用端口和套接字来侦听并相应地通过 acceptor
接受第一个调用。
相反,我希望通过另一个
socket
“伪造”AsyncReadStream
的行为。我已经考虑过自己编写,但这似乎是一项艰巨的任务,而且搜索并没有显示出太多帮助。
为了进行单元测试,可以简单地流式传输
AsyncReadStream
请求并随后将响应放入其中的 HTTP
示例是什么?如果没有,是否有某种模板,我可以用它来编写一个具有非常少的“假”功能的准系统?
对 AsyncReadStream/AsyncWriteStream 概念进行建模几乎是微不足道的
唯一的复杂性是使用 CompletionToken 模式启动异步操作:
例如:
#include <boost/asio.hpp>
#include <iostream>
#include <fmt/ranges.h>
namespace asio = boost::asio;
using namespace std::literals;
struct MockStream {
using error_code = boost::system::error_code;
using executor_type = asio::any_io_executor;
MockStream(asio::any_io_executor ex) : _ex(std::move(ex)) {}
executor_type get_executor() const { return _ex; }
template <typename Token> auto async_write_some(asio::const_buffer buf, Token&& token) {
return asio::async_initiate<Token, void(error_code, size_t)>( //
[fallback = _ex](auto h, auto buf) {
auto ex = asio::get_associated_executor(h, fallback);
asio::dispatch(ex, [=, h = std::move(h)]() mutable {
fmt::print("Simulated write of {} completed\n", buf.size());
std::move(h)({}, asio::buffer_size(buf));
});
},
token, buf);
}
template <typename Token> auto async_read_some(asio::mutable_buffer buf, Token&& token) {
return asio::async_initiate<Token, void(error_code, size_t)>( //
[fallback = _ex, ch = mock_data++](auto h, auto buf) {
auto ex = asio::get_associated_executor(h, fallback);
std::fill(asio::buffers_begin(buf), asio::buffers_end(buf), ch);
asio::dispatch(ex, [=, h = std::move(h)]() mutable {
fmt::print("Simulated read of {} completed\n", buf.size());
std::move(h)({}, asio::buffer_size(buf));
});
},
token, buf);
}
asio::any_io_executor _ex;
char mock_data = 'a';
};
int main() {
asio::io_context ioc;
MockStream stream(make_strand(ioc));
asio::async_write(stream, asio::buffer("Hello world"sv), [](auto ec, size_t n) {
fmt::print("Write completed with {} and {} bytes written\n", ec.message(), n);
});
std::array<char, 10> buf;
asio::async_read(stream, asio::buffer(buf), [&buf](auto ec, size_t n) {
fmt::print("Read completed with {} and {} bytes read: {}\n", ec.message(), n, buf);
});
asio::streambuf sbuf;
asio::async_read_until(stream, sbuf, "d", [&sbuf](auto ec, size_t n) {
fmt::print("Read-until completed with {} and {} bytes read\n", ec.message(), n);
std::cout << "Streambuf: " << &sbuf << std::endl;
});
ioc.run();
}
印刷
Simulated write of 11 completed
Write completed with Success and 11 bytes written
Simulated read of 10 completed
Read completed with Success and 10 bytes read: ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']
Simulated read of 512 completed
Simulated read of 512 completed
Simulated read of 512 completed
Read-until completed with Success and 1025 bytes read
Streambuf: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
这里有类似的实现: