2

我是性能的真正爱好者,但我也意识到执行自动化测试的重要性(直到更好的形式验证方法成为主流)。

缺点是当您尝试设计可测试性时,您开始引入接口来表示您的依赖关系。如您所知,接口使您的调用在该依赖项上动态分派,并减少了编译时的优化机会。

class MyDependency
{
    void someMethod();
}

class MyUnit
{
    // Concrete type reference of MyDependency allows 
    // to bypass the dynamic dispatch
    this(MyDependency mayBeAMock)
    {
        mayBeAMock.someMethod();
    }

    unittest
    {
        // Now how can I get a mock of my dependency without to instantiate it.
        auto dep = someBlackMagic.getMock();
        auto uut = new MyUnit(dep);
    }
}

确实存在一种更好的方法来单元测试类,而无需在生产中采用动态调度成本。如果需要,我可以负担单元测试执行的成本,但不能负担生产版本的成本。

我对 D 和 C++ 解决方案感兴趣。

4

2 回答 2

3

我在 D 中经常使用的一种技术是进行编译时策略替换:

private struct MyUtilImpl ( HTTPClient )
{
    void foo ( )
    {
        HTTPClient.makeRequest("url");
    }
}

version (unittest)
    alias MyUtil = MyUtilImpl!FakeHTTPClient;
else
    alias MyUtil = MyUtilImpl!RealHTTPClient;

它在本质上与经典的依赖注入非常相似,但不是模拟 I/O 实用程序并通过接口进行交换,而是在编译时使用模板参数执行相同的操作。

它还具有不需要更改程序其余部分的任何内容即可开始传递接口的好处。

于 2016-05-09T15:26:27.377 回答
0

2个想法。您可以将 MyUnit 设为模板并传入一个实现(或模拟)“someMethod”的类

或者,如果您的单元测试重建您正在测试的类,您可以在单独的文件中定义该类的 Mock 和真实版本,并有条件地包含/链接到您想要的类。

当然,你必须小心不要让你的测试版本与非测试版本有太大的不同。

于 2016-05-09T16:27:34.047 回答