প্যারামিটার সহ কোনও কনস্ট্রাক্টরকে মক করুন


90

নীচের মত আমার ক্লাস আছে:

public class A {
    public A(String test) {
        bla bla bla
    }

    public String check() {
        bla bla bla
    }
}

কন্সট্রাকটর যুক্তি A(String test)এবং check()কিছু আমি উপহাস করার চেষ্টা করছি হয়। আমি যেমন কোনও কল চাই: new A($$$any string$$$).check()একটি ডামি স্ট্রিং ফেরত "test"

আমি চেষ্টা করেছিলাম:

 A a = mock(A.class); 
 when(a.check()).thenReturn("test");

 String test = a.check(); // to this point, everything works. test shows as "tests"

 whenNew(A.class).withArguments(Matchers.anyString()).thenReturn(rk);
 // also tried:
 //whenNew(A.class).withParameterTypes(String.class).withArguments(Matchers.anyString()).thenReturn(rk);

 new A("random string").check();  // this doesn't work

তবে এটি কাজ করছে বলে মনে হয় না। new A($$$any string$$$).check()এর বিদ্রূপযুক্ত বস্তুটি আনার পরিবর্তে এখনও কনস্ট্রাক্টর লজিক দিয়ে চলছে A


আপনার উপহাস চেক () পদ্ধতি কি ঠিক কাজ করছে?
বেন গ্লাসার

@ বেনগ্লাসার চেক () ঠিক আছে। নতুন যখন কিছুতেই কাজ করছে না বলে মনে হচ্ছে। আমি বর্ণনাটিও আপডেট করেছি।
শেঞ্জজি

উত্তর:


93

আপনার পোস্ট করা কোডটি মকিতো এবং পাওয়ারমোকিটোর সর্বশেষতম সংস্করণটি নিয়ে আমার পক্ষে কাজ করে। আপনি কি প্রস্তুত না? এটা চেষ্টা কর:

উঃ জাভা

public class A {
     private final String test;

    public A(String test) {
        this.test = test;
    }

    public String check() {
        return "checked " + this.test;
    }
}

মকআ.জভা

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class MockA {
    @Test
    public void test_not_mocked() throws Throwable {
        assertThat(new A("random string").check(), equalTo("checked random string"));
    }
    @Test
    public void test_mocked() throws Throwable {
         A a = mock(A.class); 
         when(a.check()).thenReturn("test");
         PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a);
         assertThat(new A("random string").check(), equalTo("test"));
    }
}

উভয় পরীক্ষা মকিতো 1.9.0, পাওয়ারমকিতো 1.4.12 এবং জুনিট 4.8.2 সহ পাস করা উচিত


25
আরও মনে রাখবেন যে যদি অন্য কোনও শ্রেণি থেকে কন্সট্রাক্টরকে ফোন করা হয় তবে এটিকে তালিকায় অন্তর্ভুক্ত করুনPrepareForTest
জেফ ই

কারওই ধারণা আছে যে "পাওয়ারমকিতো.হেননিউ" বলা হলে কেন আমরা স্ব তৈরি করব?
উদয়নগ

50

আমার জ্ঞান অনুসারে, আপনি কৌতুককারী নির্মাণকারীকে মকিতো, কেবলমাত্র পদ্ধতি দ্বারা উপহাস করতে পারবেন না। তবে মকিতো গুগল কোড পৃষ্ঠায় উইকির মতে আপনার শ্রেণিতে এমন একটি পদ্ধতি তৈরি করে কনস্ট্রাক্টরর আচরণকে বিদ্রূপ করার একটি উপায় রয়েছে যা এই শ্রেণীর একটি নতুন উদাহরণ ফিরে আসে। তাহলে আপনি সেই পদ্ধতিটিকে উপহাস করতে পারেন। নীচে মকিতো উইকির সরাসরি একটি অংশ রয়েছে :

প্যাটার্ন 1 - অবজেক্ট তৈরির জন্য এক-লাইন পদ্ধতি ব্যবহার করে

প্যাটার্ন 1 ব্যবহার করতে (মাইক্লাস নামে পরিচিত একটি শ্রেণীর পরীক্ষা করা), আপনি কলটির মতো স্থান পরিবর্তন করবেন

   Foo foo = new Foo( a, b, c );

সঙ্গে

   Foo foo = makeFoo( a, b, c );

এবং একটি এক-লাইন পদ্ধতি লিখুন

   Foo makeFoo( A a, B b, C c ) { 
        return new Foo( a, b, c );
   }

এটি গুরুত্বপূর্ণ যে আপনি পদ্ধতিতে কোনও যুক্তি অন্তর্ভুক্ত করবেন না; কেবলমাত্র একটি লাইন যা বস্তু তৈরি করে। এর কারণ হ'ল পদ্ধতিটি নিজেই কখনও ইউনিট পরীক্ষিত হবে না।

আপনি যখন ক্লাসটি পরীক্ষা করতে এসেছেন, আপনি যে বস্তুর পরীক্ষা করেছেন সেটি হ'ল একটি মকিতো স্পাই হবে, এই পদ্ধতিটি উপেক্ষা করে একটি মক ফেরত দেওয়ার জন্য। আপনি যা পরীক্ষা করছেন তা ক্লাস নিজেই নয়, এটির একটি সামান্য পরিবর্তিত সংস্করণ।

আপনার পরীক্ষার শ্রেণিতে সদস্যদের মতো থাকতে পারে

  @Mock private Foo mockFoo;
  private MyClass toTest = spy(new MyClass());

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

  doReturn( mockFoo )
      .when( toTest )
      .makeFoo( any( A.class ), any( B.class ), any( C.class ));

আপনি যদি কনস্ট্রাক্টরের কাছে পাস হওয়া আর্গুমেন্টগুলি পরীক্ষা করতে চান তবে আপনি যে কোনও () এর চেয়ে বেশি সুনির্দিষ্ট ম্যাচার্স ব্যবহার করতে পারেন।

আপনি যদি কেবলমাত্র আপনার শ্রেণীর কোনও উপহাসের বিষয়টিকে ফিরিয়ে দিতে চান তবে আমি মনে করি এটি আপনার পক্ষে কাজ করা উচিত। যে কোনও ক্ষেত্রে আপনি এখানে উপহাস তৈরি সম্পর্কে আরও পড়তে পারেন:

http://code.google.com/p/mockito/wiki/MockingObjectCreation


21
+1, আমার উত্স কোডটি আরও মকিতো বান্ধব করে তুলতে আমার এডজাস্ট করা দরকার তা আমি পছন্দ করি না। ভাগ করে নেওয়ার জন্য ধন্যবাদ।
শেঞ্জজি

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

4
টেস্টেবল কোড লেখা ভাল। ক্লাস এ-কে নতুনভাবে ডিজাইন করতে বাধ্য করা হচ্ছে যাতে আমি ক্লাস বিয়ের জন্য পরীক্ষা লিখতে পারি, যা এ এর ​​উপর নির্ভরশীল, কারণ এ সি এর উপর একটি হার্ড-কোডেড নির্ভরতা রয়েছে, মনে হয় ... কম ভাল। হ্যাঁ, কোডটি শেষের দিকে আরও ভাল হবে তবে আমি আরও কতগুলি ক্লাস পুনরায় ডিজাইন করব যাতে আমি একটি পরীক্ষা লেখার কাজ শেষ করতে পারি?
মার্ক উড

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

12

পাওয়ারমক ব্যবহার না করেই .... বেন গ্লাসারের উত্তরের উপর ভিত্তি করে নীচের উদাহরণটি দেখুন কারণ এটি বের করতে আমার কিছুটা সময় লেগেছে ..হপ যা কিছু সময় সাশ্রয় করে ...

আসল ক্লাস:

public class AClazz {

    public void updateObject(CClazz cClazzObj) {
        log.debug("Bundler set.");
        cClazzObj.setBundler(new BClazz(cClazzObj, 10));
    } 
}

পরিবর্তিত শ্রেণি:

@Slf4j
public class AClazz {

    public void updateObject(CClazz cClazzObj) {
        log.debug("Bundler set.");
        cClazzObj.setBundler(getBObject(cClazzObj, 10));
    }

    protected BClazz getBObject(CClazz cClazzObj, int i) {
        return new BClazz(cClazzObj, 10);
    }
 }

পরীক্ষা ক্লাস

public class AClazzTest {

    @InjectMocks
    @Spy
    private AClazz aClazzObj;

    @Mock
    private CClazz cClazzObj;

    @Mock
    private BClazz bClassObj;

    @Before
    public void setUp() throws Exception {
        Mockito.doReturn(bClassObj)
               .when(aClazzObj)
               .getBObject(Mockito.eq(cClazzObj), Mockito.anyInt());
    }

    @Test
    public void testConfigStrategy() {
        aClazzObj.updateObject(cClazzObj);

        Mockito.verify(cClazzObj, Mockito.times(1)).setBundler(bClassObj);
    }
}

7

মকিতো দিয়ে আপনি সেটিংগুলি () ব্যবহার করতে পারেন, উদাহরণস্বরূপ, যদি কাউন্টার সার্ভিসের জন্য 2 নির্ভরতা প্রয়োজন হয় তবে আপনি সেগুলি মক হিসাবে পাস করতে পারেন:

UserService userService = Mockito.mock(UserService.class); SearchService searchService = Mockito.mock(SearchService.class); CounterService counterService = Mockito.mock(CounterService.class, withSettings().useConstructor(userService, searchService));


আমার মতে, সবচেয়ে সহজ এবং সর্বোত্তম উত্তর। ধন্যবাদ.

4

চূড়ান্ত, স্ট্যাটিক এবং ব্যক্তিগত পদ্ধতি পরীক্ষার ক্ষেত্রে মকিতোর সীমাবদ্ধতা রয়েছে।

jMockit টেস্টিং লাইব্রেরি সহ, আপনি নীচের মত খুব সহজ এবং সোজা-ফরোয়ার্ড কয়েকটি স্টাফ করতে পারেন:

Java.io.File শ্রেণীর মক নির্মাণকারী:

new MockUp<File>(){
    @Mock
    public void $init(String pathname){
        System.out.println(pathname);
        // or do whatever you want
    }
};
  • পাবলিক কনস্ট্রাক্টরের নাম $ init দিয়ে প্রতিস্থাপন করা উচিত
  • নিক্ষেপ করা যুক্তি এবং ব্যতিক্রমগুলি একই থাকে
  • রিটার্ন টাইপ অকার্যকর হিসাবে সংজ্ঞায়িত করা উচিত

একটি স্থিতিশীল পদ্ধতি উপহাস করুন:

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