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>{ /*...*/ };