কীভাবে কোনও আমদানিকে উপহাস করবেন


143

মডিউল Aঅন্তর্ভুক্ত import Bতার উপরের। তবে পরীক্ষা অবস্থার অধীনে আমি চাই উপহাস B মধ্যে A(উপহাস A.B) এবং সম্পূর্ণরূপে আমদানি করা থেকে বিরত থাকুন B

আসলে, Bউদ্দেশ্য পরীক্ষায় পরিবেশে ইনস্টল করা হয় নি।

Aপরীক্ষার অধীনে ইউনিট হয়। আমাকে এর Aসমস্ত কার্যকারিতা সহ আমদানি করতে হবে। Bআমার যে মডিউলটি উপহাস করা দরকার কিন্তু আমি কিভাবে উপহাস করতে Bমধ্যে Aএবং স্টপ Aবাস্তব আমদানি থেকে B, যদি প্রথম জিনিস Aআছে আমদানি হয় B?

(বি ইনস্টল না হওয়ার কারণটি হ'ল আমি দ্রুত পরীক্ষার জন্য পাইপি ব্যবহার করি এবং দুর্ভাগ্যক্রমে বি এখনও পাইপির সাথে সামঞ্জস্যপূর্ণ নয়))

এটি কিভাবে করা যেতে পারে?

উত্তর:


134

আপনি যা চান তা sys.modules['B']আমদানির আগে নির্ধারণ Aকরতে পারেন:

পরীক্ষা.পি :

import sys
sys.modules['B'] = __import__('mock_B')
import A

print(A.B.__name__)

এপি :

import B

দ্রষ্টব্য বিপি বিদ্যমান নেই, তবে চলার সময় test.pyকোনও ত্রুটি ফিরে আসে এবং print(A.B.__name__)মুদ্রণ করা হয় mock_B। আপনাকে এখনও এমন একটি জায়গা তৈরি করতে হবে mock_B.pyযেখানে আপনি Bআসল ফাংশন / ভেরিয়েবল / ইত্যাদি উপহাস করবেন । অথবা আপনি কেবল একটি Mock()সরাসরি বরাদ্দ করতে পারেন :

পরীক্ষা.পি :

import sys
sys.modules['B'] = Mock()
import A

3
মনে রাখবেন যে রাখা Mockকিছু জাদু বৈশিষ্ট্যাবলী (প্যাচ করা হবে না __%s__) -এর মত __name__
28:15

7
@reclosedev - আছে ম্যাজিক নকল যে জন্য
জনাথন

2
আপনি কীভাবে এটিকে পূর্বাবস্থায় ফিরিয়ে আনবেন যাতে বি আমদানি আবার আমদানি করা হয়? আমি চেষ্টা করেছি sys.modules['B'] = Noneকিন্তু মনে হচ্ছে এটি কাজ করে না।
অডিওডুড

2
পরীক্ষার শেষে আপনি কীভাবে এই উপহাসকৃত আমদানিটিকে পুনরায় সেট করবেন, যাতে অন্য ইউনিট পরীক্ষার ফাইলগুলি মশকরা দ্বারা প্রভাবিত না হয়?
রিয়া জন

1
স্পষ্টতার জন্য, আপনার উত্তরটি আসলে আমদানি করে সম্পাদনা করা উচিত mockএবং তারপরে কল করুনmock.Mock()
nmz787

28

__import__আরও নিয়ন্ত্রণের জন্য 'মক' লাইব্রেরি দিয়ে বিল্টিনকে উপহাস করা যায়:

# Store original __import__
orig_import = __import__
# This will be the B module
b_mock = mock.Mock()

def import_mock(name, *args):
    if name == 'B':
        return b_mock
    return orig_import(name, *args)

with mock.patch('__builtin__.__import__', side_effect=import_mock):
    import A

বলে Aমনে হচ্ছে:

import B

def a():
    return B.func()

A.a()প্রত্যাবর্তন b_mock.func()যা উপহাস করা যায়।

b_mock.func.return_value = 'spam'
A.a()  # returns 'spam'

পাইথন 3 এর জন্য নোট: 3.0 হিসাবে পরিবর্তনের তালিকায় বলা হয়েছে , __builtin__এখন নামকরণ করা হয়েছে builtins:

মডিউলটির নাম পরিবর্তন __builtin__করে builtins(আন্ডারস্কোরগুলি সরিয়ে, একটি 'গুলি' যুক্ত করুন)।

পাইথন 3 এর পরিবর্তে এই উত্তরের কোডটি ঠিকঠাক কাজ __builtin__করে builtins


1
কেউ কি এই কাজগুলি নিশ্চিত করেছেন? আমি দেখছি import_mockআহ্বান পেতে import A, কিন্তু কিছু এটা আমদানি জন্য নয়।
জোনাথন রাইনহার্ট

3
পাইথন ৩.৪.৩ এর সাথে আমি পেয়েছিImportError: No module named '__builtin__'
লুকাস সিমন

আপনাকে আমদানি করতে হবে__builtin__
আইডেনহজ্ব

1
@LucasCimon, প্রতিস্থাপন __builtin__দ্বারা builtinspython3 জন্য ( docs.python.org/3/whatsnew/3.0.html?highlight=__builtin__ )
লুক Marlin

17

কীভাবে একটি আমদানিকে উপহাস করবেন, (মাকে এবি)?

মডিউল এ এর ​​শীর্ষে আমদানি বি অন্তর্ভুক্ত।

সহজ, লাইব্রেরিটি sys.modules এ আমদানি করার আগে কেবল তাড়িত করুন:

if wrong_platform():
    sys.modules['B'] = mock.MagicMock()

এবং তারপরে, যতক্ষণ Aনা বি এর অবজেক্টগুলি থেকে নির্দিষ্ট ধরণের ডেটা ফেরত আসার উপর নির্ভর করে:

import A

শুধু কাজ করা উচিত।

আপনি উপহাস করতে পারেন import A.B:

আপনার সাবমডিউলগুলি থাকলেও এটি কাজ করে তবে আপনি প্রতিটি মডিউলকে উপহাস করতে চাইবেন। বলুন আপনার কাছে এটি রয়েছে:

from foo import This, That, andTheOtherThing
from foo.bar import Yada, YadaYada
from foo.baz import Blah, getBlah, boink

উপহাস করার জন্য, উপরের মডিউলটি আমদানি করার আগে কেবল নীচেটি করুন:

sys.modules['foo'] = MagicMock()
sys.modules['foo.bar'] = MagicMock()
sys.modules['foo.baz'] = MagicMock()

(আমার অভিজ্ঞতা: আমার একটি নির্ভরতা ছিল যা একটি প্ল্যাটফর্ম উইন্ডোজে কাজ করে তবে লিনাক্সে কাজ করে না, যেখানে আমরা আমাদের প্রতিদিনের পরীক্ষা চালাই So সুতরাং আমাদের পরীক্ষার জন্য আমার নির্ভরতা উপহাস করার দরকার ছিল Luck ভাগ্যক্রমে এটি একটি ব্ল্যাক বক্স ছিল, তাই আমার প্রচুর ইন্টারঅ্যাকশন সেটআপ করার দরকার নেই))

মজাদার পার্শ্ব প্রতিক্রিয়া

সংযোজন: আসলে, আমার একটি পার্শ্ব-প্রতিক্রিয়াটি অনুকরণ করা দরকার যা কিছুটা সময় নিয়েছিল। সুতরাং আমার জন্য একটি সেকেন্ডের জন্য ঘুমানোর জন্য কোনও অবজেক্টের পদ্ধতি প্রয়োজন। এটি এইভাবে কাজ করবে:

sys.modules['foo'] = MagicMock()
sys.modules['foo.bar'] = MagicMock()
sys.modules['foo.baz'] = MagicMock()
# setup the side-effect:
from time import sleep

def sleep_one(*args): 
    sleep(1)

# this gives us the mock objects that will be used
from foo.bar import MyObject 
my_instance = MyObject()
# mock the method!
my_instance.method_that_takes_time = mock.MagicMock(side_effect=sleep_one)

এবং তারপরে কোডটি বাস্তব পদ্ধতির মতো চলতে কিছুটা সময় নেয়।


7

আমি বুঝতে পারি যে আমি এখানে পার্টিতে কিছুটা দেরি করেছি, তবে mockলাইব্রেরির সাথে এটি স্বয়ংক্রিয় করার কিছুটা উন্মাদ উপায় এখানে রয়েছে :

(এখানে ব্যবহারের একটি উদাহরণ রয়েছে)

import contextlib
import collections
import mock
import sys

def fake_module(**args):
    return (collections.namedtuple('module', args.keys())(**args))

def get_patch_dict(dotted_module_path, module):
    patch_dict = {}
    module_splits = dotted_module_path.split('.')

    # Add our module to the patch dict
    patch_dict[dotted_module_path] = module

    # We add the rest of the fake modules in backwards
    while module_splits:
        # This adds the next level up into the patch dict which is a fake
        # module that points at the next level down
        patch_dict['.'.join(module_splits[:-1])] = fake_module(
            **{module_splits[-1]: patch_dict['.'.join(module_splits)]}
        )
        module_splits = module_splits[:-1]

    return patch_dict

with mock.patch.dict(
    sys.modules,
    get_patch_dict('herp.derp', fake_module(foo='bar'))
):
    import herp.derp
    # prints bar
    print herp.derp.foo

এটি এত হাস্যকর জটিল হওয়ার কারণটি যখন আমদানি ঘটে অজগরটি মূলত এটি করে (উদাহরণস্বরূপ from herp.derp import foo)

  1. না sys.modules['herp']রয়েছে? অন্যথায় এটি আমদানি। এখনও যদি না হয়ImportError
  2. না sys.modules['herp.derp']রয়েছে? অন্যথায় এটি আমদানি। এখনও যদি না হয়ImportError
  3. অ্যাট্রিবিউট পান fooএর sys.modules['herp.derp']। আরImportError
  4. foo = sys.modules['herp.derp'].foo

এই হ্যাকড একসাথে সমাধানের জন্য কিছু ডাউনসাইড রয়েছে: যদি মডিউল পথে অন্য কোনও বিষয় নির্ভর করে তবে এই জাতীয় স্ক্রুগুলি এটির উপর দিয়ে যায়। এছাড়াও এটি কেবল এমন সামগ্রীগুলির জন্য কাজ করে যা ইনলাইন যেমন আমদানি করা হচ্ছে

def foo():
    import herp.derp

অথবা

def foo():
    __import__('herp.derp')

6

অ্যারন হলের উত্তর আমার পক্ষে কাজ করে। শুধু একটি গুরুত্বপূর্ণ বিষয় উল্লেখ করতে চান,

যদি A.pyআপনি করেন

from B.C.D import E

তারপরে test.pyআপনাকে অবশ্যই প্রতিটি মডিউলটিকে পথের সাথে বিদ্রূপ করতে হবে, অন্যথায় আপনি পাবেনImportError

sys.modules['B'] = mock.MagicMock()
sys.modules['B.C'] = mock.MagicMock()
sys.modules['B.C.D'] = mock.MagicMock()

4

পাইথনে আমদানিগুলি উপহাস করার জন্য আমি দুর্দান্ত উপায় পেয়েছি। এটি এরিকের জাদি সমাধানটি এখানে পাওয়া গেছে যা আমি আমার জ্যাঙ্গো অ্যাপ্লিকেশনটির ভিতরে ব্যবহার করি use

আমি ক্লাস পেয়েছি SeatInterfaceযা Seatমডেল ক্লাস ইন্টারফেস হয় । সুতরাং আমার seat_interfaceমডিউলের ভিতরে আমার যেমন একটি আমদানি রয়েছে:

from ..models import Seat

class SeatInterface(object):
    (...)

আমি বিচ্ছিন্ন পরীক্ষার তৈরী করতে চান SeatInterfaceব্যঙ্গ সঙ্গে বর্গ Seatহিসাবে বর্গ FakeSeat। সমস্যাটি ছিল - আপনি কীভাবে অফলাইনে পরীক্ষাগুলি চালান, যেখানে জ্যাঙ্গো অ্যাপ্লিকেশনটি ডাউন রয়েছে। আমার ত্রুটি নীচে ছিল:

যথাযথ কনফিগার করা: BASE_DIR সেটিংয়ের জন্য অনুরোধ করা হয়েছে, তবে সেটিংস কনফিগার করা হয়নি। সেটিংস অ্যাক্সেস করার আগে আপনাকে অবশ্যই পরিবেশের পরিবর্তনশীল DJANGO_SETTINGS_MODULE বা কল করুন सेटिंगস কনফিগার () কল করতে হবে।

0.078 সালে 1 পরীক্ষা রান

ব্যর্থ (ত্রুটি = 1)

সমাধানটি ছিল:

import unittest
from mock import MagicMock, patch

class FakeSeat(object):
    pass

class TestSeatInterface(unittest.TestCase):

    def setUp(self):
        models_mock = MagicMock()
        models_mock.Seat.return_value = FakeSeat
        modules = {'app.app.models': models_mock}
        patch.dict('sys.modules', modules).start()

    def test1(self):
        from app.app.models_interface.seat_interface import SeatInterface

এবং তারপরে ম্যাজিকালি পরীক্ষা ঠিক আছে :)


0.002 সেকেন্ডে 1 পরীক্ষা চালানো

ঠিক আছে


3

আপনি যদি কোনও import ModuleBকাজ করেন তবে আপনি সত্যিই বিল্টিন পদ্ধতিটিকে কল করছেন __import__:

ModuleB = __import__('ModuleB', globals(), locals(), [], -1)

আপনি __builtin__মডিউলটি আমদানি করে এই পদ্ধতিটি ওভাররাইট করতে পারেন এবং __builtin__.__import__পদ্ধতিটির চারপাশে একটি মোড়ক তৈরি করতে পারেন । অথবা আপনি মডিউল NullImporterথেকে হুক সঙ্গে খেলতে পারেন imp। ব্যতিক্রমটি ধরা এবং আপনার মডিউল / শ্রেণিকে except-ব্লকটিতে মক করুন ।

সম্পর্কিত ডক্সের পয়েন্টার:

docs.python.org: __import__

ইমপ মডিউলটি দিয়ে আমদানি ইন্টার্নালগুলি অ্যাক্সেস করা হচ্ছে

আশা করি এটা কাজে লাগবে. খুব উচ্চারণে পরামর্শ দিন যে আপনি পাইথন প্রোগ্রামিংয়ের আরও তীব্রতর ঘেরে পদক্ষেপ নিয়ে যান এবং ক) আপনি কী অর্জন করতে চান তা দৃ understanding় বোঝা এবং খ) এর অর্থ সম্পর্কে পুঙ্খানুপুঙ্খ বুঝতে গুরুত্বপূর্ণ is

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.