モック - Python パッチ適用 FTP インポート

okwaves2024-01-25  8

FTP ダウンローダーの単体テストを作成しようとしています。何らかの理由で、インポートにはパッチが適用されていません。デバッグ中に、ftp オブジェクトがモックされたものではなく実際の FTP オブジェクトであることがわかります。 Python 3.5 と pytest を使用しています。

これが私のコードです:

from ftplib import FTP
from unittest.mock import patch, MagicMock


class FTPDownloader:
    def get_listing(self, host,user, password):
        ftp = FTP()
        ftp.connect(host)
        ftp.login(user, password)
        return ftp.nlst('/')


class TestMyAwesomeTest:

    @patch('ftplib.FTP', autospec=True)
    def test_get_listing(self, mock_ftp_constructor):
        mock_ftp = mock_ftp_constructor.return_value
        mock_ftp.nlst = MagicMock(return_value=['abc.csv'])
        ftp_downloader = FTPDownloader()
        listing = ftp_downloader.get_listing('ftp://foo.bar', 'user', 'password')
        assert listing == ['abc.csv']

これを実行すると、次のエラーが発生します:

socket.gaierror: [Errno -2] Name or service not known

テスト/パッチを修正して正常に実行するにはどうすればよいですか? ご協力ありがとうございました!

-編集- 私のファイルは次の場所にあります。 タグ付け/テスト/ユニット/test_my_awesome_test.py

パッチを @patch('tagging.tests.unit.test_my_awesome_test.FTP', autospec=True) に変更しても、同じエラーが発生して動作しません。

from ftlib import FTP を使用する場合は、そのインスタンスにパッチを適用する必要があります (パッチを適用する場所を参照)。または、ftplib をインポートして ftplib.FTP を使用します。

– ミスタービーン ブレーメン

2020 年 9 月 3 日 11:44



------------------------

ここでの問題は、同じファイル内のクラスにパッチを適用していることです。パッチを適用する場所で説明したデフォルトのアプローチは、テスト ファイルとは別のソース ファイルに対して機能します (通常の場合)。テストと同じファイルにソースがある場合は、patch.object を使用できます。代わりに現在のモジュールを使用します:

class TestMyAwesomeTest:

    @patch.object(sys.modules[__name__], 'FTP', autospec=True)
    def test_get_listing(self, mocked_ftp):
        mocked_ftp.return_value.nlst.return_value = ['abc.csv']
        ftp_downloader = FTPDownloader()
        listing = ftp_downloader.get_listing('ftp://foo.bar', 'user', 'password')
        assert listing == ['abc.csv']

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。