মকিতো: কীভাবে যাচাই করতে হবে কোনও পদ্ধতির মধ্যে তৈরি কোনও বস্তুর উপরে পদ্ধতিটি যাচাই করা হয়?


322

আমি মকিতোতে নতুন।

নীচের ক্লাসটি দেওয়া, আমি কীভাবে অনুরোধ করার someMethodপরে একবার অনুরোধ fooকরা হয়েছিল তা যাচাই করতে মকিটো ব্যবহার করতে পারি ?

public class Foo
{
    public void foo(){
        Bar bar = new Bar();
        bar.someMethod();
    }
}

আমি নিম্নলিখিত ভেরিফিকেশন কল করতে চাই,

verify(bar, times(1)).someMethod();

যেখানে barএকটি ব্যঙ্গ উদাহরণস্বরূপ হয় Bar


2
stackoverflow.com/questions/6520242/… - তবে আমি পাওয়ারমক ব্যবহার করতে চাই না।
মেরে

এপিআই বা পাওয়ারমক পরিবর্তন করুন। দুই এর মধ্যে এক.
জন বি

এরকম কিছু কভার করবেন কীভাবে ?? পাবলিক সিঙ্ক্রোনাইজড অকার্যকর স্টার্ট (বান্ডেলকন্টেক্সট বান্ডেল কনটেক্সট) ব্যতিক্রম ছোঁড়ে {বান্ডেলকন্টেক্সট বিসি = বান্ডেলকন্টেক্সট; logger.info ("HTTP পরিষেবা বান্ডেল শুরু হচ্ছে"); this.tracker = নতুন সার্ভিস ট্র্যাকার (বিসি, এইচটিপিএসসিএস.সি.এস। registerServlets (); ফেরত প্রদান করুন }}}
ShAkKiR

উত্তর:


365

ইনজেকশন নির্ভরতা

যদি আপনি বার ইনস্ট্যান্সটি ইনজেক্ট করেন, বা কোনও কারখানা যা বার ইনস্ট্যান্স তৈরি করার জন্য ব্যবহৃত হয় (বা এটির 483 উপায়গুলির মধ্যে একটি) তবে পরীক্ষাটি সম্পাদন করার জন্য আপনার প্রয়োজনীয় অ্যাক্সেস থাকতে হবে d

কারখানার উদাহরণ:

এভাবে লেখা একটি ফু ক্লাস দেওয়া:

public class Foo {
  private BarFactory barFactory;

  public Foo(BarFactory factory) {
    this.barFactory = factory;
  }

  public void foo() {
    Bar bar = this.barFactory.createBar();
    bar.someMethod();
  }
}

আপনার পরীক্ষার পদ্ধতিতে আপনি এই জাতীয় বারফ্যাক্টরি ইনজেকশন করতে পারেন:

@Test
public void testDoFoo() {
  Bar bar = mock(Bar.class);
  BarFactory myFactory = new BarFactory() {
    public Bar createBar() { return bar;}
  };

  Foo foo = new Foo(myFactory);
  foo.foo();

  verify(bar, times(1)).someMethod();
}

বোনাস: এটি কীভাবে টিডিডি আপনার কোডের নকশা চালাতে পারে তার একটি উদাহরণ।


6
ইউনিট পরীক্ষার জন্য ক্লাসটি পরিবর্তন না করে এটি করার কোনও উপায় আছে কি?
মেরে

6
Bar bar = mock(Bar.class)পরিবর্তেBar bar = new Bar();
জন বি

7
আমার এরকম কিছু জানা নেই. তবে, আমি আপনাকে ইউনিট পরীক্ষার জন্য ক্লাসটি পরিবর্তন করার পরামর্শ দিচ্ছি না। এটি সত্যিই ক্লিন কোড এবং এসআরপি সম্পর্কে কথোপকথন। বা .. বার অবজেক্ট তৈরি করা ক্লাস ফু-তে মেথড ফু () এর দায়িত্ব কি? যদি উত্তর হ্যাঁ হয়, তবে এটি বাস্তবায়নের বিশদ এবং আপনার বিশেষভাবে ইন্টারঅ্যাকশনটি পরীক্ষা করার বিষয়ে চিন্তা করা উচিত নয় (@ মাইকেল এর উত্তর দেখুন)। উত্তরটি যদি না হয় তবে আপনি ক্লাসটি পরিবর্তন করছেন কারণ পরীক্ষার ক্ষেত্রে আপনার অসুবিধা একটি লাল পতাকা যা আপনার ডিজাইনের সামান্য উন্নতি প্রয়োজন (অতএব আমি যে বোনাসটি যুক্ত করেছি পুনরায় টিডিডি ড্রাইভগুলি কীভাবে চালায়)।
সিস্ট্র্টজ

3
আপনি কি মকিতোর "যাচাইকরণ" এ "সত্য" অবজেক্টটি পাস করতে পারবেন?
জন বি

4
আপনি কারখানাটিকেও উপহাস করতে পারেন: BarFactory myFactory = mock(BarFactory.class); when(myFactory.createBar()).thenReturn(bar);
লেভসা

18

ক্লাসিক প্রতিক্রিয়াটি হ'ল, "আপনি করেন না।" আপনি Fooএর অভ্যন্তরীণ নয়, এর সর্বজনীন এপিআই পরীক্ষা করেন ।

এর Fooদ্বারা প্রভাবিত কোন বস্তুর (বা, ভাল ভাল, পরিবেশের কোনও অন্য বস্তু) আচরণ রয়েছে foo()? যদি তা হয় তবে তা পরীক্ষা করে দেখুন। এবং যদি না হয়, পদ্ধতিটি কী করে?


4
তাহলে আপনি এখানে আসলে কি পরীক্ষা করবেন? পাবলিক এপিআই Fooহয় public void foo(), যেখানে অভ্যন্তরীণ হয় শুধুমাত্র এর সাথে সম্পর্কিত দণ্ড।
বেহিলিট

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

@ ডাফজে আমি জাভা ব্যবহার করি না, তবে এটি এমন কিছু মনে হয় যা আপনার সংকলক বা কোড বিশ্লেষণ সরঞ্জাম সনাক্ত করতে পারে।
ব্যবহারকারী 247702

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

13

আপনি ডিআই বা কারখানা ব্যবহার করতে না চাইলে। আপনি নিজের ক্লাসটিকে কিছুটা কৌশলে রিফ্যাক্টর করতে পারেন:

public class Foo {
    private Bar bar;

    public void foo(Bar bar){
        this.bar = (bar != null) ? bar : new Bar();
        bar.someMethod();
        this.bar = null;  // for simulating local scope
    }
}

এবং আপনার পরীক্ষার শ্রেণি:

@RunWith(MockitoJUnitRunner.class)
public class FooTest {
    @Mock Bar barMock;
    Foo foo;

    @Test
    public void testFoo() {
       foo = new Foo();
       foo.foo(barMock);
       verify(barMock, times(1)).someMethod();
    }
}

তারপরে যে ক্লাসটি আপনার foo পদ্ধতিটি কল করছে এটি এটি এইভাবে করবে:

public class thirdClass {

   public void someOtherMethod() {
      Foo myFoo = new Foo();
      myFoo.foo(null);
   }
}

আপনি যেমন পদ্ধতিটি কল করার সময় দেখতে পাচ্ছেন যে আপনার অন্য কোনও ক্লাসে বার ক্লাসটি আমদানির দরকার নেই যা আপনার ফু পদ্ধতিটি কল করছে যা সম্ভবত আপনি চান।

অবশ্যই খারাপ দিকটি হ'ল আপনি কলারটিকে বার অবজেক্ট সেট করার অনুমতি দিচ্ছেন।

আশা করি এটা সাহায্য করবে.


3
আমি মনে করি এটি একটি অ্যান্টি-প্যাটার্ন। নির্ভরতা ইনজেকশন করা উচিত, সময়কাল। কেবলমাত্র পরীক্ষার উদ্দেশ্যে optionচ্ছিকভাবে ইনজেকশনের নির্ভরতা দেওয়া ইচ্ছাকৃতভাবে কোড উন্নত করা এড়ানো এবং ইচ্ছাকৃতভাবে কোডটিতে প্রযোজ্য কোডের চেয়ে আলাদা কিছু পরীক্ষা করছে। এই দুটিই করণীয়, ভয়ঙ্কর কাজ।
এরিক

8

আপনার উদাহরণ কোড ব্যবহার করে সমাধান PowerMockito.whenNew

  • মকিতো-সমস্ত 1.10.8
  • পাওয়ারমক-কোর 1.6.1
  • পাওয়ারমক-মডিউল-জুনিট 4 1.6.1
  • পাওয়ারমক-এপি-মকিতো 1.6.1
  • জুনিট 4.12

FooTest.java

package foo;

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

//Both @PrepareForTest and @RunWith are needed for `whenNew` to work 
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Foo.class })
public class FooTest {

    // Class Under Test
    Foo cut;

    @Mock
    Bar barMock;

    @Before
    public void setUp() throws Exception {
        cut = new Foo();

    }

    @After
    public void tearDown() {
        cut = null;

    }

    @Test
    public void testFoo() throws Exception {

        // Setup
        PowerMockito.whenNew(Bar.class).withNoArguments()
                .thenReturn(this.barMock);

        // Test
        cut.foo();

        // Validations
        Mockito.verify(this.barMock, Mockito.times(1)).someMethod();

    }

}

JUnit আউটপুট JUnit আউটপুট


8

আমি মনে করি মকিতো @InjectMocksহ'ল উপায়।

আপনার অভিপ্রায় অনুসারে আপনি ব্যবহার করতে পারেন:

  1. কনস্ট্রাক্টর ইনজেকশন
  2. সম্পত্তি সেটার ইনজেকশন
  3. মাঠের ইনজেকশন

ডক্সে আরও তথ্য

মাঠের ইনজেকশন সহ নীচে একটি উদাহরণ দেওয়া হল:

ক্লাস:

public class Foo
{
    private Bar bar = new Bar();

    public void foo() 
    {
        bar.someMethod();
    }
}

public class Bar
{
    public void someMethod()
    {
         //something
    }
}

টেস্ট:

@RunWith(MockitoJUnitRunner.class)
public class FooTest
{
    @Mock
    Bar bar;

    @InjectMocks
    Foo foo;

    @Test
    public void FooTest()
    {
        doNothing().when( bar ).someMethod();
        foo.foo();
        verify(bar, times(1)).someMethod();
    }
}

3

হ্যাঁ, আপনি যদি সত্যিই এটি করতে চান / প্রয়োজন হয় তবে আপনি পাওয়ারমক ব্যবহার করতে পারেন। এটি একটি সর্বশেষ অবলম্বন হিসাবে বিবেচনা করা উচিত। পাওয়ারমক দিয়ে আপনি কলটি থেকে কনস্ট্রাক্টরকে একটি মক ফিরিয়ে আনতে পারেন। তারপরে মকটিতে যাচাই করুন। এটি বলেছিল, সিস্ট্র্টজ হ'ল "সঠিক" উত্তর।

এখানে নতুন অবজেক্টগুলির মোক নির্মাণের লিঙ্কটি রয়েছে


0

আরেকটি সহজ উপায় হ'ল বারে কিছু লগ স্টেটমেন্ট যুক্ত করা হবে ome সোমমথোড () এবং তারপরে আপনার পরীক্ষাটি কার্যকর হওয়ার সময় আপনি যে বার্তাটি দেখতে পাচ্ছেন তা নিশ্চিত করুন, উদাহরণগুলি এখানে দেখুন: লগরে কোনও বার্তায় JUnit দৃ to়করণ কীভাবে করবেন

বিশেষ করে কুশলী যখন আপনার Bar.someMethod () হল private

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