2011-04-08 66 views
4

我是新来的测试和TDD,但决定尝试和学习。目前我正在尝试开发一个类SettingsManager来处理我的应用程序的设置。它将存储应用程序的状态以及关闭时间SettingsManager将使用QSettings保存状态(并在启动时读取)。现在我想模拟QSettings,所以我的测试不会依赖随机状态。但是,我找不到任何明智的方式来模拟/保留它,因为我需要的方法(QSettings :: value())不是虚拟的。如何存根/模拟Qt类?

也许我在做一些概念上的错误?或者有没有办法模拟这个非虚拟的方法调用?

例子:假设我有这个类:

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); 
} 

回答

2

我想你是单位测试QSettings,但这不是单元测试的重点。

如果你想学习TDD,从简单的事情开始。例如,尝试创建MVP三元组类(模型和演示者应具有接口,而视图是qt类类型)。然后完全单元测试模型和演示者。该视图不应该有任何逻辑 - 只有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 2011-04-08 14:27:35

+0

我不想测试QSettings。我想从QSettings中得到不同的预定义返回值,所以我可以确定我的类中的逻辑的行为如预期。例如,如果QSettings返回的值为空或注册表中没有这样的字段会怎么样?手动检查这些条件非常耗时,所以我想知道是否有办法模拟QSettings? – ashagi 2011-04-11 04:22:44

+1

@ashagi您可以将类型QSettings的对象传递给SettingsManager类型的对象,在该对象中创建对该对象的引用。然后在测试中,您可以在QSettings对象中设置各种字段,并检查SettingsManager的方法是否返回期望值。 – 2011-04-11 08:26:30