我正在使用QThreadPool
在应用程序中并行运行任务。任务将线程池作为参数,因此它们可以启动新任务。如何编写任务的单元测试并断言正确的下一个任务已启动?
class MyTask: public QRunnable {
public:
virtual void run() {
m_threadPool.start(/*another task*/);
m_threadPool.start(/*a third task*/);
}
private:
QThreadPool &m_threadPool;
};
我想测试MyTask
:
QThreadPool threadPool;
threadPool.start(new MyTask(threadPool));
threadPool.waitForDone();
// Assert that another task and a third task is started.
我尝试扩展QThreadPool
并记录启动的任务:
class MyThreadPool : public QThreadPool {
public:
virtual void start(QRunnable *runnable, int priority = 0) {
m_Queue.enqueue(runnable);
// The task is not started, so I can manually start each task and test the outcome.
}
QQueue<QRunnable *> queue() const { return m_queue; }
private:
QQueue<QRunnable *> m_queue;
};
MyThreadPool threadPool;
threadPool.start(new MyTask(threadPool));
threadPool.waitForDone();
QQueue<QRunnable *> Queue({ /*another task and a third task*/ });
Assert::IsEquavalent(threadPool.queue(), Queue);
但这不起作用,因为QThreadPool::start()
不是虚拟的。编写测试的最佳方法是什么?
答案 0 :(得分:0)
关于QThreadPool::start()
不是虚函数的问题,您可以执行以下操作:
您可以在MyTask中使用子类,而不使用覆盖函数的其他函数来调用run。像这样:
class MyThreadPool : public QThreadPool {
public:
void enqueue_and_run(QRunnable *runnable, int priority = 0) {
m_Queue.enqueue(runnable);
QThreadPool::start(runnable, priority);
}
const QQueue<QRunnable *>& queue() const {
return m_queue;
}
private:
QQueue<QRunnable *> m_queue;
};
class MyTask: public QRunnable {
public:
virtual void run() {
m_threadPool.enqueue_and_run(/*another task*/);
m_threadPool.enqueue_and_run(/*a third task*/);
}
private:
MyThreadPool &m_threadPool;
};
再运行相同的测试代码:
MyThreadPool threadPool;
threadPool.enqueue_and_run(new MyTask(threadPool));
threadPool.waitForDone();
QQueue<QRunnable *> Queue({ /*another task and a third task*/ });
Assert::IsEquavalent(threadPool.queue(), Queue);
这不是最优雅的方法,但可以明确您的意图。
作为替代方案,如果要保留公共接口,则可以使用基本函数重载:
template <class TPool>
void start(TPool* pool, QRunnable *runnable, int priority = 0) {
pool->start(runnable, priority);
}
void start(MyThreadPool* pool, QRunnable *runnable, int priority = 0) {
pool->enqueue_and_run(pool, runnable, priority);
}
然后您的测试代码将与原始代码相似:
MyThreadPool threadPool;
start(threadPool, new MyTask(threadPool));
threadPool.waitForDone();
// ... rest of the code