2016-09-07 6 views
1

Я пытаюсь сделать модульное тестирование для проверки метода DoLogin:Как вводить макет объекта?

CLoginActivity::CLoginActivity() 
{ 
    m_pTask = new Task(); 
} 

void CLoginActivity::DoLogin() 
{ 
    m_pTask.execute(); 
} 

где Task еще один класс, который мне нужно издеваться.

class MockTask : public Task 
{ 
public: 
    MOCK_METHOD0(Execute, void()); 

}; 

Чтобы впрыскивать MockTask task объект, я должен изменить конструкцию:

CLoginActivity::CLoginActivity(Task& task) 
{ 
    m_pTask = task; 
} 

или написать набор функций:

CLoginActivity::SetTask(Task& task) 
{ 
    m_pTask = task; 
} 

Есть ли другой способ, чтобы ввести вместо этих двух методов? И я использую gmock в своем модульном тестовом проекте.

ответ

2

Впрыскивание через конструктор является лучшим - сохраните этот дизайн.

Но есть несколько других способов для людей, которые любят усложнять простые вещи.

1) Сделайте свой шаблон класса CLoginActivity:

template <class TaskImpl> 
class CLoginActivityTemplate 
{ 
     CLoginActivityTemplate() { m_pTask = new TaskImpl(); } 
}; 

using CLoginActivity = CLoginActivityTemplate<Task>; 

В своих тестах, проверить это instantion:

using CLoginActivityTestable = CLoginActivityTemplate<TaskMock>; 

Однако это не всегда так просто - потому что часто бывает трудно получить доступ к этому макету, чтобы установить расширения на нем. Но вы можете определить класс TestMockWrapper для обеспечения доступа к притворной задаче легко:

class TestMockWrapper : public TestMock 
{ 
public: 
    static TestMock* lastCreated; 
    TestMockWrapper() { lastCreated = this; } 
}; 
using CLoginActivityTestable = CLoginActivityTemplate<TaskMockWrapper>; 

2) Вводить объект фабричного конструктора:

CLoginActivity::CLoginActivity(ITaskFactory& taskFactory) 
{ 
    m_pTask = taskFactory.create(); 
} 

Вам нужно издеваться этим классом фабрики для обеспечения mock- фабрика создает макет-объект. Может быть, это не выглядит обещанием - но это только введение к следующей точке.

3) Есть специальная функция завода реализуется в другом файле:

CLoginActivity.cpp

#include "TaskCreate.hpp" 

CLoginActivity::CLoginActivity() 
{ 
    m_pTask = taskCreate(); 
} 

TaskCreate.cpp

// your "real" function here 
ITask* createTask() { return new Task(); } 

Имея такие дизайн- создать тест UT для CLoginActivity с использованием только выбранных файлов из ваших проектов - просто говоря - заменить TaskCreate.cpp с TaskcreateStub.cpp в вашем проекте UT:

  1. CloginActivity.cpp
  2. TaskMock. CPP (если существует)
  3. TaskCreateStub.cpp

TaskCreateStub.cpp должен возвращать задачу-mock - не настоящую задачу. Вам также нужен доступ к этому возвращенному макету-объекту, поэтому вы можете установить на него ожидания.

TaskCreateStub.cpp

// your "real" function here 
static TaskMock* taskMockForCreateStub = nullptr; 
ITask* createTask() { return taskMockForCreateStub ; } 
void setTaskMockForCreateTaskStub(TaskMock* taskMock) { taskMockForCreateStub = taskMock; } 

Я сильно отговорить вас от использования такого линкер уровня насмешки. Используйте его только для тестирования устаревшего кода, где вы не можете его перепроектировать, и это может быть единственным способом использования макета ...

Смежные вопросы