3

問題

単体テストを作成する必要があるUDPlistenerアプリケーションがあります。このリスナーはポートで継続的にリッスンし、常に製品で実行されるようになっています。標準ライブラリにないフレームワークにはpocoライブラリを使用します。

次に、単体テストアプリケーションに追加する必要があります。

現在のソリューション

アプリケーションを実行Poco::Runnableするクラスに実装するのが最も簡単だと思いました。次に、ユニットテストでRunApp新しいクラスを作成してクラスを実行できます。Poco::ThreadRunApp

これは機能します。リスナーが実行されており、スレッドが生成された後、単体テスト本体でテストメッセージを送信できます。ただし、他の単体テストを実行できるように、リスナーを停止する必要があります。リスナーに自殺するように指示するUDPメッセージを追加しましたが、これは単体テストと潜在的なセキュリティ問題によってのみ使用されます。

質問

を強制的Poco::Threadに停止する方法はありますか?または、この単体テストの構成が間違っていますか?他のすべての単体テスト中にリスナーを実行したくありません。

4

1 に答える 1

8

を使用する代わりに、Poco::Threadを使用するとPoco::Task、キャンセルできるスレッドが得られます。次のサンプルコード(そのまま実行する準備ができています)は、あなたにアイデアを与えるはずです:

#include <Poco/Task.h>
#include <Poco/TaskManager.h>
#include <Poco/Thread.h>

#include <string>
#include <iostream>
using namespace std;

class UdpListenerTask : public Poco::Task {
public:
    UdpListenerTask(const string& name) : Task(name) { }

    void runTask() {
        cout << name() << ": starting" << endl;
        while (! isCancelled()) {
            // Do some work. Cannot block indefinitely, otherwise it
            // will never test the isCancelled() condition.
            doSomeWork();
        }
        cout << endl << name() << ": cancelled " << endl;
    }
private:
    int doSomeWork() {
        cout << "*" << flush;
        // Simulate some time spent doing work
        int i;
        for (i = 0; i < INT32_MAX/1000; i++) { }
        return i;
    }
};

void runUdpProbe() {
    // Simulate some time spent running the probe.
    Poco::Thread::sleep(1000);
}

int main() {
    Poco::TaskManager tm;
    UdpListenerTask* st = new UdpListenerTask("task1");
    tm.start(st); // tm takes ownership

    // Run test 1.
    runUdpProbe();
    // Test 1 done. Cancel the UDP listener
    st->cancel();

    // Run all the other tests

    // cleanup
    tm.joinAll();
    return 0;
}

POCOスライドマルチスレッドは、Poco::ThreadとPoco::Taskの両方の使用例を示しています。

余談ですが、単体テストでは、抽象クラスとモックオブジェクトを介したUDP通信をバイパスする必要があります。このテストは機能テストと呼ばれるべきだと思います:-)

于 2012-06-21T08:41:36.247 に答える