2

「while True」ループで実行されているワーカーを持つマルチプロセッシング アプリケーションがあります。テストのために、次のような方法で sys.exit() をモックできるようにしたいと思います。

with mock.patch('sys.exit') as sys_mock:
  sys_mock.side_effect = break

また

with mock.patch('sys.exit') as sys_mock:
  sys_mock.side_effect = return

そのため、ループから抜け出し、テストを完了することができます。これらはどちらも機能しませんが、私が達成しようとしていることを行う別の方法はありますか?

4

1 に答える 1

3

Exceptionasを使用して、テストを終了せずに動作side_effectをシミュレートできます。sys.exit

side_effectドキュメンテーションは言う:

これは、モックが呼び出されたときに呼び出される関数、イテラブル、または発生する例外 (クラスまたはインスタンス) のいずれかです。

したがって、 orのようなステートメントを使用することはできませんが、やりたいことは実行サイクルを終了することであり、例外を発生させることで取得できます...スレッドのメインサイクルでワイルドを使用しないことを願っています。breakreturntryexcept

それをテストするための簡単な例を書きました。デコレーター構文を使用し、テストを読みやすくするためpatchにインラインにしました。side_effect=Exception

import sys
import threading
import unittest
from unittest.mock import patch

class T(threading.Thread):
    def __init__(self,  *args, **kwargs):
        super(T, self).__init__(*args, **kwargs)
        self._interrupt = threading.Event()
        self.started = threading.Event() #Used to be sure that we test run() behavior 
        self.started.clear()
        self.terminated = False

    def interrupt(self):
        self._interrupt.set()

    def run(self, *args, **kwargs):
        self._interrupt.clear()
        self.started.set()
        while not self._interrupt.is_set():
            self._interrupt.wait(timeout=1)
        self.terminated = True
        sys.exit()


class TestInterrupt(unittest.TestCase):

    @patch("sys.exit", side_effect=Exception("Ignore it... just close thread"))
    def test_interrupt(self, mock_sys_exit):
        t = T()
        t.start()
        if not t.started.is_set():
            t.started.wait(timeout=0.2)
        self.assertTrue(t.started.is_set(), "t not started!")
        #Ok t is in run() main cycle: we can test interrupt
        t.interrupt()
        t.join(0.1)
        self.assertTrue(t.terminated)
        self.assertFalse(t.isAlive())
于 2015-02-20T08:32:44.513 に答える