মক অবজেক্টগুলি শুরু করা হচ্ছে - মকআইটো


122

মকআইটো ব্যবহার করে মক অবজেক্টটি শুরু করার বিভিন্ন উপায় রয়েছে। এর মধ্যে সেরা উপায় কী?

1।

 public class SampleBaseTestCase {

   @Before public void initMocks() {
       MockitoAnnotations.initMocks(this);
   }

2।

@RunWith(MockitoJUnitRunner.class)

[সম্পাদনা] 3।

mock(XXX.class);

এর চেয়ে ভাল অন্য কোনও উপায় থাকলে আমাকে পরামর্শ দিন ...

উত্তর:


153

মক ইনিশিয়ালেশনের জন্য , রানার ব্যবহার করে বা এটি MockitoAnnotations.initMocksকঠোরভাবে সমতুল্য সমাধান। এর javadoc থেকে MockitoJUnitRunner :

JUnit 4.5 runner initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary. Mocks are initialized before each test method.


MockitoAnnotations.initMocksযখন আপনি ইতিমধ্যে SpringJUnit4ClassRunnerআপনার পরীক্ষার ক্ষেত্রে কোনও নির্দিষ্ট রানার ( উদাহরণস্বরূপ) কনফিগার করেছেন তখন প্রথম সমাধানটি (এর সাথে ) ব্যবহার করা যেতে পারে ।

দ্বিতীয় সমাধানটি (এর সাথে MockitoJUnitRunner) আরও ক্লাসিক এবং আমার প্রিয়। কোডটি সহজ। রানার ব্যবহারের বড় সুবিধা প্রদান করে ফ্রেমওয়ার্ক ব্যবহার স্বয়ংক্রিয় বৈধতা (বর্ণনা @David ওয়ালেস মধ্যে এই উত্তর )।

উভয় সমাধান পরীক্ষার পদ্ধতির মধ্যে মক (এবং গুপ্তচরদের) ভাগ করে নিতে দেয়। এর সাথে মিলিত হয়ে @InjectMocksতারা খুব দ্রুত ইউনিট পরীক্ষা লেখার অনুমতি দেয়। বয়লারপ্লেট মকিং কোড হ্রাস পেয়েছে, পরীক্ষাগুলি পড়া সহজ। উদাহরণ স্বরূপ:

@RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {

    @Mock private ArticleCalculator calculator;
    @Mock(name = "database") private ArticleDatabase dbMock;
    @Spy private UserProvider userProvider = new ConsumerUserProvider();

    @InjectMocks private ArticleManager manager;

    @Test public void shouldDoSomething() {
        manager.initiateArticle();
        verify(database).addListener(any(ArticleListener.class));
    }

    @Test public void shouldDoSomethingElse() {
        manager.finishArticle();
        verify(database).removeListener(any(ArticleListener.class));
    }
}

পেশাদাররা: কোডটি ন্যূনতম

কনস: কালো যাদু। আইএমও এটি মূলত @ ইনজেক্টমোকস টীকা দেওয়ার কারণে। এই টীকাটি দিয়ে "আপনি কোডের ব্যথাটি শিথিল করেছেন" ( @ ব্রাইসের দুর্দান্ত মন্তব্য দেখুন )


তৃতীয় সমাধানটি প্রতিটি পরীক্ষার পদ্ধতিতে আপনার মক তৈরি করা। এটি @ এম কে কে এর উত্তরে ব্যাখ্যা হিসাবে " স্বনির্ভর পরীক্ষা " করার অনুমতি দেয়।

public class ArticleManagerTest {

    @Test public void shouldDoSomething() {
        // given
        ArticleCalculator calculator = mock(ArticleCalculator.class);
        ArticleDatabase database = mock(ArticleDatabase.class);
        UserProvider userProvider = spy(new ConsumerUserProvider());
        ArticleManager manager = new ArticleManager(calculator, 
                                                    userProvider, 
                                                    database);

        // when 
        manager.initiateArticle();

        // then 
        verify(database).addListener(any(ArticleListener.class));
    }

    @Test public void shouldDoSomethingElse() {
        // given
        ArticleCalculator calculator = mock(ArticleCalculator.class);
        ArticleDatabase database = mock(ArticleDatabase.class);
        UserProvider userProvider = spy(new ConsumerUserProvider());
        ArticleManager manager = new ArticleManager(calculator, 
                                                    userProvider, 
                                                    database);

        // when 
        manager.finishArticle();

        // then
        verify(database).removeListener(any(ArticleListener.class));
    }
}

পেশাদাররা: আপনার এপিআই কীভাবে কাজ করে তা আপনি স্পষ্টভাবে প্রদর্শন করেছেন (বিডিডি ...)

কনস: আরও বেশি বয়লারপ্লেট কোড রয়েছে। (বিদ্রূপ সৃষ্টি)


আমার ক্ষতিপূরণ একটি আপস। এর @Mockসাথে টীকাটি ব্যবহার করুন @RunWith(MockitoJUnitRunner.class), তবে এটি ব্যবহার করবেন না @InjectMocks:

@RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {

    @Mock private ArticleCalculator calculator;
    @Mock private ArticleDatabase database;
    @Spy private UserProvider userProvider = new ConsumerUserProvider();

    @Test public void shouldDoSomething() {
        // given
        ArticleManager manager = new ArticleManager(calculator, 
                                                    userProvider, 
                                                    database);

        // when 
        manager.initiateArticle();

        // then 
        verify(database).addListener(any(ArticleListener.class));
    }

    @Test public void shouldDoSomethingElse() {
        // given
        ArticleManager manager = new ArticleManager(calculator, 
                                                    userProvider, 
                                                    database);

        // when 
        manager.finishArticle();

        // then 
        verify(database).removeListener(any(ArticleListener.class));
    }
}

পেশাদাররা: আপনার এপিআই কীভাবে কাজ করে তা আপনি স্পষ্টভাবে প্রদর্শন করেছেন (আমার কীভাবে ArticleManagerতাত্ক্ষণিক হয়)। কোনও বয়লারপ্লেট কোড নেই।

কনস: পরীক্ষাটি স্ব-অন্তর্ভুক্ত নয়, কোডের কম ব্যথা


যদিও সাবধান থাকুন, টীকাগুলি দরকারী তবে এগুলি আপনাকে ও ও ডিজাইনের খারাপ নকশা (বা এটিকে অবনমিত করতে) রক্ষা করতে পারে না। ব্যক্তিগতভাবে আমি বয়লারপ্লেট কোড হ্রাস করতে পেরে খুশি, আমি কোড (বা পিআইটিএ) এর যন্ত্রণাটি আলগা করি যা নকশাকে আরও ভাল রূপায়িত করার ট্রিগার, তাই আমি এবং টিম ওও ডিজাইনের দিকে মনোযোগ দিচ্ছি। আমি অনুভব করি যে সলিড ডিজাইন বা জিওএস আইডিয়াসের মতো নীতিগুলির সাথে ওও ডিজাইন অনুসরণ করা কীভাবে মককে তাত্ক্ষণিকভাবে বেছে নেওয়া যায় তা চয়ন করা আরও গুরুত্বপূর্ণ।
ব্রাইস

1
(ফলোআপ) আপনি যদি না দেখেন যে এই বস্তুটি কীভাবে তৈরি করা হয় তবে আপনি এটি সম্পর্কে ব্যথা অনুভব করবেন না এবং নতুন কার্যকারিতা যুক্ত করা উচিত হলে ভবিষ্যতের প্রোগ্রামাররা ভাল প্রতিক্রিয়া জানাতে পারে না। যাইহোক এটি উভয় উপায়ে তর্কযোগ্য, আমি কেবল এটি সম্পর্কে সতর্ক হতে বলছি।
ব্রাইস

6
এটি সঠিক নয় যে এই দুটি সমতুল্য। এটি সহজ নয় যে সহজ কোডটিই কেবল ব্যবহারের সুবিধা MockitoJUnitRunner। পার্থক্য সম্পর্কে আরও তথ্যের জন্য, স্ট্যাকওভারফ্লো . com/ প্রশ্নগুলি ১০০৮০634545৫/২ এ প্রশ্নটি দেখুন এবং এর উত্তর আমার।
দাউদ ইবনে কেরেম

2
@ গন্টার্ড হ্যাঁ নিশ্চিত নির্ভরতা দৃশ্যমান, তবে আমি এই পদ্ধতি ব্যবহার করে কোডটি ভুল হতে দেখেছি। ব্যবহার সম্পর্কে Collaborator collab = mock(Collaborator.class), আমার মতে এই উপায়টি অবশ্যই একটি বৈধ পন্থা। যদিও এটি ভার্জোজ হতে পারে, আপনি পরীক্ষাগুলির বোধগম্যতা এবং পুনঃসারণযোগ্যতা অর্জন করতে পারেন। উভয় উপায়ে তাদের পক্ষে মতামত রয়েছে, আমি কোন সিদ্ধান্ত নিতে পারছি তা এখনও ঠিক করি নি। অ্যামওয়ে বর্ননা লিখতে সবসময়ই সম্ভব এবং সম্ভবত প্রসঙ্গ এবং কোডারের উপর নির্ভর করে।
ব্রাইস

1
@ এম কে কে আমি আপনার সাথে সম্পূর্ণ একমত আমার ইংরাজী খুব ভাল নয় এবং এতে কিছুটা ঘাটতি নেই। আমার বক্তব্য ছিল ইউএনআইটি শব্দের প্রতি জোর দেওয়া।
gontard

30

মোক (ইনস্টিটিউট) করার চতুর্থ উপায় এখন (v1.10.7 হিসাবে) রয়েছে, যা মকিতোরুল নামে একটি JUnit4 নিয়ম ব্যবহার করছে

@RunWith(JUnit4.class)   // or a different runner of your choice
public class YourTest
  @Rule public MockitoRule rule = MockitoJUnit.rule();
  @Mock public YourMock yourMock;

  @Test public void yourTestMethod() { /* ... */ }
}

জন্য JUnit সৌন্দর্য TestRule এর উপশ্রেণী @Rule সঙ্গে সটীক এবং তাদের ব্যবহারের পরীক্ষা বিবৃতি মোড়ানো যে রানার প্রদান করে । এর ফলস্বরূপ হ'ল আপনি @ পূর্বে পদ্ধতিগুলি, @ পরবর্তী পদ্ধতিগুলি, এবং এমনকি নিয়মগুলিতে র‌্যাপারগুলি ধরতে চেষ্টা করতে পারেন। এমনকি আপনি নিজের পরীক্ষার মধ্য দিয়েই এগুলির সাথে ইন্টারেক্ট করতে পারবেন, যেভাবে প্রত্যাশিত এক্সপ্লেশনটি করে।

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

সংক্ষেপে:

  • Mockito.mock(): কোনও টীকা সমর্থন বা ব্যবহারের বৈধতা ছাড়াই সরাসরি অনুরোধ।
  • MockitoAnnotations.initMocks(this): টীকা সমর্থন, কোন ব্যবহারের বৈধতা।
  • MockitoJUnitRunner: টীকা সমর্থন এবং ব্যবহারের বৈধতা, কিন্তু আপনাকে অবশ্যই সেই রানারটি ব্যবহার করতে হবে।
  • MockitoRule: যে কোনও JUnit রানারের সাথে টিক চিহ্ন সমর্থন এবং ব্যবহারের বৈধতা।

আরও দেখুন: JUnit @ Rule কীভাবে কাজ করে?


3
কোটলিনে, নিয়মটি এরকম দেখাচ্ছে:@get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
ক্রাইস্তান

10

এটি করার একটি ঝরঝরে উপায় আছে।

  • এটি যদি ইউনিটের পরীক্ষা হয় তবে আপনি এটি করতে পারেন:

    @RunWith(MockitoJUnitRunner.class)
    public class MyUnitTest {
    
        @Mock
        private MyFirstMock myFirstMock;
    
        @Mock
        private MySecondMock mySecondMock;
    
        @Spy
        private MySpiedClass mySpiedClass = new MySpiedClass();
    
        // It's gonna inject the 2 mocks and the spied object per reflection to this object
        // The java doc of @InjectMocks explains it really well how and when it does the injection
        @InjectMocks
        private MyClassToTest myClassToTest;
    
        @Test
        public void testSomething() {
        }
    }
  • সম্পাদনা: এটি যদি একীকরণের পরীক্ষা হয় তবে আপনি এটি করতে পারেন (স্প্রিংয়ের সাথে সেভাবে ব্যবহারের উদ্দেশ্যে নয় Just কেবল প্রদর্শন করুন যে আপনি বিচ্ছিন্ন রানারদের সাথে মক শুরু করতে পারেন):

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("aplicationContext.xml")
    public class MyIntegrationTest {
    
        @Mock
        private MyFirstMock myFirstMock;
    
        @Mock
        private MySecondMock mySecondMock;
    
        @Spy
        private MySpiedClass mySpiedClass = new MySpiedClass();
    
        // It's gonna inject the 2 mocks and the spied object per reflection to this object
        // The java doc of @InjectMocks explains it really well how and when it does the injection
        @InjectMocks
        private MyClassToTest myClassToTest;
    
        @Before
        public void setUp() throws Exception {
              MockitoAnnotations.initMocks(this);
        }
    
        @Test
        public void testSomething() {
        }
    }

1
যদি এমওকেকে ইন্টিগ্রেশন টেস্টগুলিতেও জড়িত থাকে, তবে তা কি অর্থবোধ করে?
বিনয়ভেলুরি

2
আসলে এটি হবে না, আপনার অধিকার। আমি কেবল মকিতোর সম্ভাবনাগুলি দেখাতে চেয়েছিলাম। উদাহরণস্বরূপ যদি আপনার ব্যবহারের আরএসটিফিউজ করে তবে আপনি তাদের রানার ব্যবহার করতে পারেন যাতে আপনি মকিতোঅনোটেশন.ইনটমকস (এটি) দিয়ে মকগুলি শুরু করতে পারেন;
এমডি

8

মকিটোঅনোটেশন এবং রানার উপরে উপরে ভালভাবে আলোচনা হয়েছে, সুতরাং আমি অখাদ্যদের জন্য আমার প্রবণতাটি ফেলে যাচ্ছি:

XXX mockedXxx = mock(XXX.class);

আমি এটি ব্যবহার করি কারণ আমি এটিকে কিছুটা বর্ণনামূলক বলে মনে করি এবং আমার পরীক্ষাগুলি (যতটা তারা হতে পারে) নিজের মধ্যে থাকতে চাই বলে আমি সদস্যের ভেরিয়েবলগুলি ব্যবহার না করা (ডান নিষেধাজ্ঞার বাইরে নয়) ইউনিট পরীক্ষাগুলি পছন্দ করি।


পরীক্ষার কেসকে স্বতঃস্ফূর্ত করে তোলা ব্যতীত মক (এক্সএক্স.এল.ক্লাস) ব্যবহার করা ছাড়া অন্য কোনও সুবিধা আছে কি?
VinayVeluri

আমি যতটা সচেতন না।
মাইকেল লয়েড লি mlk

3
পরীক্ষা পড়ার জন্য কম ম্যাজিক বুঝতে হবে। আপনি ভেরিয়েবল ডিক্লেয়ার, এবং এটি একটি মূল্য দিতে - কোনো টীকা, প্রতিফলন ইত্যাদি
Karu

2

জুনিট 5 বৃহস্পতির ছোট্ট উদাহরণ, "রানউইথ" সরানো হয়েছে এখন আপনাকে "@ এক্সটেন্ডুইথ" এনটেশন ব্যবহার করে এক্সটেনশনগুলি ব্যবহার করতে হবে।

@ExtendWith(MockitoExtension.class)
class FooTest {

  @InjectMocks
  ClassUnderTest test = new ClassUnderTest();

  @Spy
  SomeInject bla = new SomeInject();
}

0

অন্যান্য উত্তরগুলি দুর্দান্ত এবং আপনি যদি তাদের প্রয়োজন / প্রয়োজন চান তবে আরও বিশদ থাকে।
এগুলি ছাড়াও, আমি একটি টিএল যোগ করতে চাই; ডিআর:

  1. ব্যবহার পছন্দ
    • @RunWith(MockitoJUnitRunner.class)
  2. যদি আপনি না করতে পারেন (কারণ আপনি ইতিমধ্যে একটি ভিন্ন রানার ব্যবহার করেছেন), তবে ব্যবহার করতে পছন্দ করুন
    • @Rule public MockitoRule rule = MockitoJUnit.rule();
  3. (2) এর মতো, তবে আপনার এটি আর ব্যবহার করা উচিত নয় :
    • @Before public void initMocks() { MockitoAnnotations.initMocks(this); }
  4. আপনি যদি কেবল একটি পরীক্ষায় একটি মোক ব্যবহার করতে চান এবং এটি একই পরীক্ষার শ্রেণিতে অন্য পরীক্ষায় প্রকাশ করতে না চান তবে ব্যবহার করুন
    • X x = mock(X.class)

(1) এবং (2) এবং (3) পারস্পরিক একচেটিয়া।
(4) অন্যের সাথে সংমিশ্রণে ব্যবহার করা যেতে পারে।

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