如何使用google test在单元测试中模拟不同的时区

C++: How to simulate different timezones in unit tests using google test

本文关键字:模拟 时区 单元测试 何使用 google test      更新时间:2023-10-16

我正在使用c++与Google测试进行单元测试。在我们的公司代码中,我们仍然有这个问题,系统数据类型(例如CTime)使用实际系统的时区(我们使用CTime数据类型的方式与在生产代码中相同)。对于单元测试,我们想要模拟不同的时区,因为我们在这方面有很多问题。

我已经花了很多时间研究别人是怎么做的,因为这是不可能的,其他公司没有这个问题:)但是我没有找到一个解决方案。我的想法是这样的:CTime本身保存UTC时间,并根据需要将其转换为当地时间。我的假设是,所有这些函数都需要在timezonapi.h中声明的GetTimeZoneInformation()函数。

WINBASEAPI
_Success_(return != TIME_ZONE_ID_INVALID)
DWORD
WINAPI
GetTimeZoneInformation(_Out_ LPTIME_ZONE_INFORMATION lpTimeZoneInformation);

所以解决方案可能是通过自定义函数交换这个GetTimeZoneInformation()功能,然后返回一个我可以根据需要更改的对象。但是我不知道怎么做,我也不知道这是否工作,因为它可能只在应用程序启动时调用这个函数一次。

有人知道如何处理这个话题吗?我不想改变任何行为,我只想能够在不破坏任何时间计算机制的情况下设置自己的时区。最好的情况是,我可以在不更改生产代码的情况下模拟这些调用。问题是这个项目非常庞大,历史悠久,而且……尽可能少的改变永远是最好的:)

如果我还没有找到一个已经存在的帖子来解决我的问题,那么我真的很抱歉,因为我要么没有找到它,要么我没有得到这个可以帮助我。

正如你在问题中提到的,嘲讽是解决这个问题的好方法。

我所知道的最快和最简单的方法是将你想要测试的所有方法包装在一个新类中,它实现了"策略"设计模式:

它可以在实际实现和模拟之间切换,一旦将逻辑设置为模拟,它将返回模拟值。

默认情况下应该设置为实际实现。

int Foo()的简单示例:

    Class Strategy{
            int Foo() = o
    }
    Class StrategyImplementation
    {
    private:
            Strategy* logic;
    public:
            void SetLogic(Strategy* newLogic){logic=newLogic)}
            int Foo(){return logic->Foo()}
    }
    Class mock : public Strategy{
    public:
            SetValue(int value){this.value = value}
            int Foo(){return value}
    private:
            int value;
        }
    Class Implementation  : public Strategy{
        int Foo(){ here_you_call_the_method_you_want_to_test }
    }

剩下的就是将GetTimeZoneInformation的每次调用更改为新的Strategy,最简单的方法就是使用"Singleton"设计模式。

它没有高风险,您需要做的更改是将调用从'Foo()'更改为'StrategyImplementation::GetInstance().Foo()'