Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 被测试类的模拟依赖关系_C++_Visual Studio_Unit Testing_Mocking_Embedded - Fatal编程技术网

C++ 被测试类的模拟依赖关系

C++ 被测试类的模拟依赖关系,c++,visual-studio,unit-testing,mocking,embedded,C++,Visual Studio,Unit Testing,Mocking,Embedded,我想测试一些编写用于在VisualStudio本机单元测试项目中的嵌入式处理器上运行的代码 TestMe类有几种方法可以很好地进行测试,但Foo和Bar类直接访问仅在嵌入式处理器上可用的内存映射寄存器 #pragma once #include "Foo.h" #include "Bar.h" class TestMe { public: TestMe(Foo& aFoo, Bar& aBar); ~TestMe(); float FooBar();

我想测试一些编写用于在VisualStudio本机单元测试项目中的嵌入式处理器上运行的代码

TestMe类有几种方法可以很好地进行测试,但Foo和Bar类直接访问仅在嵌入式处理器上可用的内存映射寄存器

#pragma once

#include "Foo.h"
#include "Bar.h"

class TestMe
{
public:
    TestMe(Foo& aFoo, Bar& aBar);
    ~TestMe();

    float FooBar();

};
模仿这些对象以便测试TestMe类的最佳方法是什么

编辑:对我来说,最好的方法是尽可能少地干扰正在测试的软件

“最佳”总是主观的,但我喜欢使用模板进行此类模拟:

template <typename TFoo, typename TBar>
class TestMeImpl
{
public:
    TestMeImpl(TFoo& aFoo, TBar& aBar);
    ~TestMeImpl();

    float FooBar();
};

using TestMe = TestMeImpl<Foo, Bar>;
模板
类TestMeImpl
{
公众:
TestMeImpl(TFoo和aFoo、TBar和aBar);
~TestMeImpl();
float FooBar();
};
使用TestMe=TestMeImpl;

您可以针对
TestMeImpl
编写单元测试,但将
TestMe
公开给您的用户。

您的
Foo
Bar
通过引用传递给构造函数。 这有两种方法

我个人喜欢使用接口并利用多态对象

看起来是这样的:

class IFoo {
public:
     virtual void someFunction() = 0;
};

class IBar {
public:
     virtual void otherFunction() = 0;
};

class Foo : public IFoo {
    ....
    void someFunction() {
    }
};

class Bar : public IBar {
     .....
     void otherFunction() {
     }  
};

class TestMe {
public:
    TestMe(IFoo& aFoo, IBar& aBar);
    ~TestMe();

    float FooBar();
};

// test code (GMock example):
class MockFoo : public IFoo {
    MOCK_METHOD(someFunction(), void());
};

class MockBar : public IBar {
     MOCK_METHOD(otherFunction(), void());
};

TEST(TestMeTest, someTest)
{
   MockBar bar;
   MockFoo foo; 
   TestMe testMe(bar, foo);

   EXPECT_CALL(bar, otherFunction());

   EXPECT_EQ(0.2, testMe.FooBar());
}
这与使用模板基本相同。在这种情况下,使用了动态多态性。 在模板的情况下,你得到了一些类似的东西,所以有些人称之为静态多态性


这两种方法都有优缺点,您可以决定哪种方法最适合您。

有一种解决方案,不只是为了测试目的而引入接口(: 链接时间替换

规则:

  • Foo和Bar位于静态lib中(Foo和Bar可以有单独的lib)
  • 不要将这些lib链接到testexec
  • 创建将链接到test exec的模拟实现:
Hpp文件:

#pragma once
#include <gmock/gmock.h>

class FooMock
{
    FooMock();
    ~FooMock();

    MOCK_METHOD0(foo, void());
};
缺点是它不适用于多线程测试。
希望有帮助。

根据嵌入式平台的大小和性能限制,引入接口仅用于单元测试可能不是一个好主意。对于小型系统,我倾向于使用表示某种处理器外围设备的类型别名类。我猜这也是“Foo”和“Bar”的含义在你的例子中代表

可以使用体系结构预定义为当前目标选择正确的类型别名

struct Uart1 {};
struct Uart1Mock {};

#ifdef __x86_64__
    using SensorUart = Uart1Mock;
#else
    using SensorUart = Uart1;
#endif

然后,应用程序代码只使用SensorUart,无论该类是依赖于实际串行端口还是仅使用标准io。

您是将其放在单独的文件中还是放在TestMe.h中?我想如果我必须对许多类执行此操作,这将导致项目中出现大量与测试相关的代码。@Q-bertsuit:可能是一个单独的文件,因为它避免了这种情况Week
TestMeImpl
Foo
/
Bar
之间存在不必要的物理依赖关系。你说的“很多”是什么意思您现有的实现将成为模板,而唯一的额外代码是<代码>使用指令。因此,您将创建一个名为TestMeMy.Tpp和TestMe.h的新文件,它只包含“包含”和“使用”指令。这听起来很合理。问题很好,“包含”的标题不太好。请考虑重命名为“正在测试的类的模拟依赖项”。@MarekR谢谢,标题已更新
struct Uart1 {};
struct Uart1Mock {};

#ifdef __x86_64__
    using SensorUart = Uart1Mock;
#else
    using SensorUart = Uart1;
#endif