如何对Qt类进行存根/模拟?

10
我是一名新手测试和TDD,但决定尝试并学习。目前我正在尝试开发一个名为SettingsManager的类,该类将处理我的应用程序的设置。它将存储应用程序的状态,并在关闭SettingsManager时保存状态使用QSettings(并在启动时读取)。现在,我想模拟QSettings,以便我的测试不依赖于随机状态。然而,我找不到任何明智的方法来模拟/存根它,因为我需要的方法(QSettings :: value())不是虚拟的。
也许我在概念上做错了什么?或者有没有一种方法可以模拟那个非虚拟方法调用?
例如:假设我有这个类:
class SettingsManager
{    
private:
    /* app state variables */
    QSettings *settings;
    bool m_objectsVisible;

public:

    SettingsManager(QSettings *settings)
    {
       this->settings = settings;
    }

    void readSettings()
    {
       m_objectsVisible = settings.value("Settings/ObjectsVisible").toBool();
    }

    bool objectsVisible()
    {
       return m_objectsVisible;
    }
};

我希望以这种方式进行测试(我使用Hippomocks语法只是为了给出一个想法)。
void TestObjectsAreVisible() {
    MockRepository mocks;
    QSettings *settingsMock = mocks.ClassMock<QSettings>();
    mocks.ExpectCall(settingsMock , QSettings::value).With("Settings/ObjectsVisible").Return(true);
    SettingsManager *sManager = new SettingsManager(settingsMock);
    sManager->readSettings();
    assertTrue(sManager->objectsVisible);
}
1个回答

2
我认为你正在对QSettings进行单元测试,但这并不是单元测试的重点。
如果你想学习TDD,请从简单的东西开始。例如,尝试创建一个MVP三元组类(模型和Presenter应该有接口,而视图是qt类类型)。然后完全对模型和Presenter进行单元测试。视图不应该有任何逻辑 - 只有qt调用。
类似这样:
struct View : (some qt object )
{
  View( PresenterIface &p_ ) : p(p_) {}

  void buttonClicked()
  {
    p.buttonClicked();
  }

  PresenterIface p;
};

struct Presenter : PresenterIface
{
 Presenter( ModelIface &m_ ) : m(m){}
 void buttonClicked()
 {
  m.setValue();
 }

 ModelIface &m;
};

struct Model : ModelIface
{
  void setValue()
  {
    // do something
  }
};

3
赞同。不要测试 QSettings。测试保存应用程序设置的类。 - Jay
1
我并不是试图测试QSettings。我想从QSettings获取不同的预定义返回值,以确保我的类中的逻辑表现符合预期。例如,如果QSettings返回的值为空或注册表中没有这样的字段,那该怎么办?手动检查这些条件很耗时间,所以我想知道是否有一种方法可以模拟QSettings? - ashagi
1
@ashagi,您可以将类型为 QSettings 的对象传递给类型为 SettingsManager 的对象,在那里创建对该对象的引用。然后,在您的测试中,您可以设置 QSettings 对象中的各种字段,并检查 SettingsManager 的方法是否返回预期值。 - BЈовић
似乎这是我可以使用的最佳选项。无论如何,我希望在单元测试中使用虚拟对象来摆脱这个依赖性。谢谢你的建议! - ashagi
2
这个问题是完全有效的,而答案却根本没有回答它。但是关于只传递不同的QSettings对象的评论似乎是唯一的好主意。 - IceFire

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接