如何让这些课程更加适合单元测试呢?

时间:2016-02-04 16:00:12

标签: c++ unit-testing

我有一个包含规则的二进制文件。我将这些规则解析为对象并针对它们扫描文件。我当前的对象模型是这样的:

struct TypeARule
{
    // rule internals
};

struct TypeBRule
{
    // rule internals
};

struct TypeCRule
{
    // rule internals
};

struct RuleDatabase
{
    vector<TypeARule> TypeA;
    vector<TypeBRule> TypeB;
    vector<TypeCRule> TypeC;
};

class RuleParser
{
public:
    bool ParseFile(const string& path, RuleDatabase& database)
    {
        // open file, read records from file, generate objects from records, add objects to database
    }
private:
    // misc helper methods
};

class RuleScanner
{
public:
    bool ScanFile(const string& path, const RuleDatabase& database)
    {
        if(ScanTypeA(path, database))
        {
            return true;
        }
        if(ScanTypeB(path, database))
        {
            return true;
        }
        if(ScanTypeC(path, database))
        {
            return true;
        }
        return false;
    }
private:
    bool ScanTypeA(const string& path, const RuleDatabase& database)
    {
        for(const auto& rule : database.TypeA)
        {
            if (rule matches path))
            {
                return true;
            }
        }
        return false;
    }
    bool ScanTypeB(const string& path, const RuleDatabase& database)
    {
        for(const auto& rule : database.TypeB)
        {
            if (rule matches path))
            {
                return true;
            }
        }
        return false;
    }
    bool ScanTypeC(const string& path, const RuleDatabase& database)
    {
        for(const auto& rule : database.TypeA)
        {
            if (rule matches path))
            {
                return true;
            }
        }
        return false;
    }
};

class Client
{
public:
    bool Initialize(const string& path)
    {
        RuleParser parser;
        return parser.ParseFile(path, m_database);
    }
    bool ScanFile(const string& path)
    {
        RuleScanner scanner;
        return scanner.ScanFile(path, m_database);
    }
    void Cleanup()
    {
        // cleanup m_database
    }
private:
    RuleDatabase m_database;
};

我理解依赖注入有助于测试Client类(通过将对模拟RuleParserRuleScanner对象的引用传递给它的构造函数)。但是,我需要做些什么才能对RuleParserRuleScanner类进行单元测试?由于RuleDatabase是用于存储其他对象的哑对象,因此依赖注入在当前模型中不起作用。我最初的想法是修改RuleDatabase以隐藏其数据成员并提供对其进行操作的公共方法,例如ParseTypeA()ParseTypeB()ScanTypeA()ScanTypeB() 。然而,在我看来,这似乎模糊了职业责任之间的界限(例如RuleParser应该完成所有的解析工作,而RuleScanner应该完成所有的扫描工作。有更清洁的方法吗?

2 个答案:

答案 0 :(得分:1)

istream传递给ParseFile方法。这样,您可以在测试文件中以istringstream创建流,而无需为测试提供文件。

您可能最好使用TDD通过测试来帮助推动课程设计。设计测试类比测试现有设计总是更容易。

答案 1 :(得分:1)

使用Inversion of Control principle(通常称为IoC),这样您就可以独立地测试您的课程。

但是不要陷入极端,像标量类型一样保留简单的类,只需对它们进行单元测试。

在您的情况下,我会从您的RuleParser课程中将RuleScannerClient课程外部化。

您的RuleScanner类也可以通过插入要实现的接口来获取可以外部化的规则列表,因此您将能够单独测试每个规则。