CRTP 静态多态性:是否可以用 mock 替换基础 class?
CRTP static polymorphism: is it possible to replace the base class with a mock?
我在 websocket 服务器中使用 CRTP 静态多态性来将网络代码与业务逻辑分离。基 class 调用派生的方法来处理消息,派生又调用基 send/receive。它像魅力一样工作,看起来像这样:
template<typename Derived>
class WebsocketSessionBase {
// basic websocket send/receive stuff
void someBaseMethod() {
static_cast<Derived*>(this)->otherDerivedMethod();
}
};
class WebsocketSession : public WebsocketSessionBase<WebsocketSession> {
// specific business logic
void someDerivedMethod() {
otherBaseMethod();
}
};
现在进行单元测试。由于代码是解耦的,我希望在 classes 中单独测试功能。
测试基础 class 很简单:
class TestSession : public WebsocketSessionBase<TestSession> {
// same interface as WebsocketSession, but test code, cool!
};
但是我如何测试导出的 class?我想到了添加一个 Base 模板参数,这使得测试代码没问题(Base 是一个 mock class)。但我最终在生产版本中有 2 个模板 classes 相互引用......:(
template<typename Base>
class TestableWebsocketSession : public Base {
};
using TestedWebsocketSession = TestableWebsocketSession<MockBase>;
using ProdWebSocketSession = TestableWebsocketSession<WebsocketSessionBase<... // infinite loop - now what!?
这个可以过来吗?
我不知道这是否值得,但您可以使 WebsocketSession 成为一个 class 模板,使用模板模板参数:
template<class T>
struct WebsocketSessionBase { /*...*/ };
template<template<class> class B>
struct WebsocketSessionDerived: B<WebsocketSessionDerived<B>>{ /*...*/ };
using WebsocketSession = WebsocketSessionDerived<WebsocketSessionBase>;
using DerivedTestSession = WebsocketSessionDerived<WebsocketSessionMockBase>;
struct BaseTestSession : WebsocketSessionBase<BaseTestSession>{ /*...*/ };
我在 websocket 服务器中使用 CRTP 静态多态性来将网络代码与业务逻辑分离。基 class 调用派生的方法来处理消息,派生又调用基 send/receive。它像魅力一样工作,看起来像这样:
template<typename Derived>
class WebsocketSessionBase {
// basic websocket send/receive stuff
void someBaseMethod() {
static_cast<Derived*>(this)->otherDerivedMethod();
}
};
class WebsocketSession : public WebsocketSessionBase<WebsocketSession> {
// specific business logic
void someDerivedMethod() {
otherBaseMethod();
}
};
现在进行单元测试。由于代码是解耦的,我希望在 classes 中单独测试功能。
测试基础 class 很简单:
class TestSession : public WebsocketSessionBase<TestSession> {
// same interface as WebsocketSession, but test code, cool!
};
但是我如何测试导出的 class?我想到了添加一个 Base 模板参数,这使得测试代码没问题(Base 是一个 mock class)。但我最终在生产版本中有 2 个模板 classes 相互引用......:(
template<typename Base>
class TestableWebsocketSession : public Base {
};
using TestedWebsocketSession = TestableWebsocketSession<MockBase>;
using ProdWebSocketSession = TestableWebsocketSession<WebsocketSessionBase<... // infinite loop - now what!?
这个可以过来吗?
我不知道这是否值得,但您可以使 WebsocketSession 成为一个 class 模板,使用模板模板参数:
template<class T>
struct WebsocketSessionBase { /*...*/ };
template<template<class> class B>
struct WebsocketSessionDerived: B<WebsocketSessionDerived<B>>{ /*...*/ };
using WebsocketSession = WebsocketSessionDerived<WebsocketSessionBase>;
using DerivedTestSession = WebsocketSessionDerived<WebsocketSessionMockBase>;
struct BaseTestSession : WebsocketSessionBase<BaseTestSession>{ /*...*/ };