假设我有课程:
class Foo : public QObject{
Q_OBJECT
public:
...
private:
Bar* m_bar;
}
无论出于何种原因,我想用指向DerivedBar对象的指针替换m_bar。我经常发现的用例是当我想用MockBar的对象(使用google模拟框架)替换它进行单元测试时。
现在我知道在大多数情况下,我可以将构造函数扩展为:
Foo(Bar* bar, QObject* parent)
然后相应地设置m_bar。
但我遇到的问题是这些类是QWidgets而我是通过Qt Designer组装的。想象一下Foo和Bar是小工具,Bar被设计师放在Foo里面;它们的连接也是通过设计器设置的(即存储在qml文件中)。我尝试过类似的东西:
Bar* bar = foo.findChild<Bar*>();
bar = new MockBar(&foo);
(忽略任何内存泄漏,只是试图获得功能)但是当我设定期望时,它似乎没有像现有的那样连接。不响应信号而调用时隙。由于连接的方式,我不认为这是完全出乎意料的,但我想知道是否有办法获得我正在寻找的效果。
(nb:目前,使用qt 4.8和gcc 4.6,它确实限制了c ++的一些选项
答案 0 :(得分:0)
这是我发现的一个更好的答案:对我来说问题最终是关于从ui文件生成的QWidgets。但由于Ui :: FooWidget类在功能上只是一个pimpl模式,我可以创建一个指向本地副本的指针,并修改Foo的构造函数以允许我选择性地注入ui实现。如果Foo正在对BarWidget进行直接函数调用,我可以用我的MockBarWidget替换该ui的'barWidget'对象,并设置期望等并执行测试。当两个小部件之间的交互是信号/插槽连接之一时,上一个答案仍然会在一定程度上满足。
上一个答案:
这是我到目前为止找到的一个答案,但我不太喜欢它:
Bar* bar = foo.findChild<Bar*>();
bool connectTest = QObject::connect(&foo, SIGNAL(setValue(int)), bar, SLOT(setValue(int)), Qt::UniqueConnection);
ASSERT_FALSE(connectTest);
bar = new MockBar(&foo);
connectTest = QObject::connect(&foo, SIGNAL(setValue(int)), bar, SLOT(setValue(int)), Qt::UniqueConnection);
ASSERT_TRUE(connectTest);
//... rest of test
我可以用某种辅助函数包装整个东西,并且c ++ 11 / Qt5中的函数可能更好,其中信号和槽可以是方法指针。但我想知道我是否错过了一种更简单的方法。
编辑:事实证明这种模式给了我一个误报,只有测试的第一个'connectTest'部分给出了有效的行为测试。当Foo没有向bar发出信号时,这个缺陷更明显,但只是在bar上调用一个方法。模拟不是通过这种模式注入的。