মকিতো: ব্যক্তিগত @ অটোভায়ার্ড ফিল্ডগুলিতে আসল অবজেক্ট ইনজেকশন করুন


190

আমি স্প্রিংয়ের সাথে টীকাযুক্ত ব্যক্তিগত ক্ষেত্রগুলিতে নির্ভরতা ইনজেকশন করতে মকিতো @Mockএবং @InjectMocksটীকাগুলি ব্যবহার করছি @Autowired:

@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
    @Mock
    private SomeService service;

    @InjectMocks
    private Demo demo;

    /* ... */
}

এবং

public class Demo {

    @Autowired
    private SomeService service;

    /* ... */
}

এখন আমি ব্যক্তিগত ক্ষেত্রগুলিতে (সেটটার ছাড়াই) প্রকৃত বস্তুগুলিও ইনজেকশন করতে চাই @Autowired। এটি কি সম্ভব বা কেবল মকসকে ইনজেকশন দেওয়ার মধ্যেই কি এই প্রক্রিয়াটি সীমাবদ্ধ?


5
সাধারণত যখন আপনি জিনিসগুলি উপহাস করছেন, তখন এর থেকে বোঝা যায় যে আপনি কংক্রিটের বিষয়ে খুব বেশি যত্ন নিচ্ছেন না; যে আপনি কেবল বিদ্রূপযুক্ত বস্তুর আচরণ সম্পর্কেই যত্নশীল হন। এর বদলে আপনি কি ইন্টিগ্রেশন টেস্ট করতে চান? বা, আপনি কেন উপহাস এবং কংক্রিটের জিনিসগুলি একসাথে থাকতে চান তা সম্পর্কে একটি যুক্তি সরবরাহ করতে পারেন?
মাকোটো

2
ঠিক আছে, আমি লিগ্যাসি কোডটি নিয়ে কাজ করছি এবং এতে অনেকগুলি সময় লাগবে (...) তখন কিছু এনপিই এবং এর মতো প্রতিরোধের জন্য মক সেটআপ করার জন্য পুনরায় (...) বিবৃতিগুলি পুনর্বার করা হবে। অন্যদিকে, একটি সত্যিকারের বস্তু এটির জন্য নিরাপদে ব্যবহার করা যেতে পারে। তাই উপহাসের সাথে আসল বস্তুগুলি ইনজেক্ট করার বিকল্প থাকা খুব সহজ হবে। এমনকি এটি কোনও কোডের গন্ধ হতে পারে, তবে আমি এই বিশেষ ক্ষেত্রে এটি যুক্তিসঙ্গত মনে করি।
ব্যবহারকারী 2286693

ভুলবেন না MockitoAnnotations.initMocks(this);যে @Beforeপদ্ধতি। আমি জানি এটি আসল প্রশ্নের সাথে সরাসরি সম্পর্কিত নয়, তবে পরবর্তী সময়ে যে কারও সাথেই আসছেন, এই রান চালানোর জন্য এটি যুক্ত করা দরকার।
কুগা

7
@ কুগা: আপনি যদি ইউনিত, ( @RunWith(MockitoJUnitRunner.class)) এর জন্য মকিতো রানার ব্যবহার করেন তবে আপনার লাইনের দরকার নেইMockitoAnnotations.initMocks(this);
ক্লিন্ট ইস্টউড

1
ধন্যবাদ - আমি তা কখনই জানতাম না এবং সবসময়ই দুজনকেই নির্দিষ্ট করে দিয়েছিলাম
কুগা

উত্তর:


304

@Spyটীকাটি ব্যবহার করুন

@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
    @Spy
    private SomeService service = new RealServiceImpl();

    @InjectMocks
    private Demo demo;

    /* ... */
}

মকিতো সম্ভাব্য প্রার্থী হিসাবে টীকাগুলির সাথে টীকাগুলির ক্ষেত্রে ইনজেকশনের হিসাবে সমস্ত ক্ষেত্র রয়েছে @Mockবা @Spyটীকাগুলি বিবেচনা করবে @InjectMocks। উপরের ক্ষেত্রে 'RealServiceImpl'উদাহরণটি 'ডেমো' তে প্রবেশ করবে

আরও তথ্যের জন্য দেখুন

Mockito বাড়িতে

@Spy

@উপহাস


9
+1: স্ট্রিং অবজেক্ট ছাড়া আমার জন্য ... মকিতো অভিযোগ করেছেন:Mockito cannot mock/spy following: - final classes - anonymous classes - primitive types
অ্যাড্রিয়ান প্রোঙ্ক

ধন্যবাদ এটি আমার পক্ষেও কাজ করেছে :) প্রকৃত প্রয়োগের জন্য গুপ্তচর ব্যবহারের জন্য প্রক্সি ব্যবহারের উপহাস তৈরি করতে
স্বরিত আগরওয়াল

ধন্যবাদ! আমার যা প্রয়োজন ঠিক তা-ও!
nterry

2
আমার ক্ষেত্রে, মকিতো কোনও গুপ্তচরকে ইনজেকশন দিচ্ছে না । এটি যদিও মক ইনজেকশন দেয়। ক্ষেত্রটি বেসরকারী এবং একটি সেটর ছাড়াই।
ভিটুইল

8
বিটিডাব্লু, এর কোনও প্রয়োজন নেই new RealServiceImpl(), @Spy private SomeService service;যাইহোক এটির গুপ্তচরবৃত্তি করার আগে ডিফল্ট কনস্ট্রাক্টর ব্যবহার করে একটি আসল অবজেক্ট তৈরি করে।
parxier

20

@ ডেভ ব্লঙ্কড উত্তর ছাড়াও, আপনি যদি একটি বিদ্যমান শিম ব্যবহার করতে চান যা বসন্তের দ্বারা তৈরি করা হয়েছিল কোডটি এখানে পরিবর্তন করা যেতে পারে:

@RunWith(MockitoJUnitRunner.class)
public class DemoTest {

    @Inject
    private ApplicationContext ctx;

    @Spy
    private SomeService service;

    @InjectMocks
    private Demo demo;

    @Before
    public void setUp(){
        service = ctx.getBean(SomeService.class);
    }

    /* ... */
}

এইভাবে কেবল পরীক্ষাগুলি কার্যকর করার জন্য আপনার কোড পরিবর্তন করতে হবে না (অন্য নির্মাণকারী যুক্ত করুন)।


2
@ আডা আপনি কি বিস্তারিত বর্ণনা করতে পারেন?
Yoaz Menda

1
এটি কোন লাইব্রেরি থেকে আসে, আমি কেবল org.mockito ইনজেকশন মক্স দেখতে পারি
সমীর

1
@ সমীর আমদানি করুন org.mockito.InjectMocks;
ইয়োজ মেন্দা

আডাকে বাতিল করতে একটি মন্তব্য যুক্ত করা হচ্ছে। এটি আমার পক্ষে কাজ করেছে। অন্যান্য উত্তরের পরামর্শ অনুসারে আমি "ফিল্ড ইনজেকশনটি কেবল ব্যবহার করতে পারি না", তাই আমাকে Autowiredনির্ভর করতে হবে ক্ষেত্রগুলি নির্ভরতা থেকে সঠিকভাবে তৈরি হয়েছিল।
স্ক্রাম্বো

1
আমি এই চেষ্টা করেছি। তবে আমি সেটআপ পদ্ধতি থেকে নাল পয়েন্টার ব্যতিক্রমটি পেয়েছি
আখিল সুরপুরম

3

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

@Mock
private SomeService serviceMock;

private Demo demo;

/* ... */
@BeforeEach
public void beforeEach(){
   demo = new Demo(serviceMock);
}

spyসাধারণ ক্ষেত্রে মকিতো ব্যবহার করা একটি ভয়ানক পরামর্শ। এটি পরীক্ষার শ্রেণিকে ভঙ্গুর করে তোলে, সোজা এবং ত্রুটিযুক্ত না: আসলে কী উপহাস করা হয়? আসলেই কী পরীক্ষা করা হয়?
@InjectMocksএবং @Spyএছাড়াও সামগ্রিক নকশা ব্যাথা যেহেতু এটি স্ফীত ক্লাস এবং ক্লাসের মিশ্র দায়িত্ব উৎসাহিত করে। অন্ধভাবে ব্যবহার করার আগে
দয়া করে spy()জাভাডোকটি পড়ুন (জোর আমার নয়):

আসল বস্তুর একটি গুপ্তচর তৈরি করে। গুপ্তচর সত্যিকারের পদ্ধতিগুলি কল করে যদি না তাদের স্ট্যাব করা হয়। বাস্তব গুপ্তচরগুলি যত্ন সহকারে এবং মাঝে মাঝে ব্যবহার করা উচিত , উদাহরণস্বরূপ যখন উত্তরাধিকারের কোডটি নিয়ে কাজ করা হয়।

যথারীতি আপনি পড়তে যাচ্ছেন partial mock warning: অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং জটিলতাটিকে আলাদা, নির্দিষ্ট, এসআরপি আইজে বিভক্ত করে জটিলতার সাথে লড়াই করে। আংশিক মক কীভাবে এই দৃষ্টান্তের মধ্যে ফিট করে? ঠিক আছে, এটি ঠিক নয় ... আংশিক উপহাসের অর্থ সাধারণত জটিলটি একই জিনিসটিতে ভিন্ন পদ্ধতিতে স্থানান্তরিত হয়েছিল। বেশিরভাগ ক্ষেত্রে, আপনি নিজের অ্যাপ্লিকেশনটি ডিজাইন করতে চান না।

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


0

বসন্তে ReflectionTestUtilsএই উদ্দেশ্যে একটি উত্সর্গীকৃত ইউটিলিটি ডাকা হয় । নির্দিষ্ট উদাহরণটি ধরুন এবং ক্ষেত্রটি ইনজেক্ট করুন।


@Spy
..
@Mock
..

@InjectMock
Foo foo;

@BeforeEach
void _before(){
   ReflectionTestUtils.setField(foo,"bar", new BarImpl());// `bar` is private field
}

-1

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে স্ট্রিংস ইনজেকশনের চেষ্টা করার সময় আমরা একই সমস্যায় পড়েছিলাম। সুতরাং আমরা একটি JUnit5 / মকিতো এক্সটেনশন আবিষ্কার করেছি যা আপনি যা চান ঠিক তা করে: https://github.com/exabrial/mockito-object-inication

সম্পাদনা করুন:

@InjectionMap
 private Map<String, Object> injectionMap = new HashMap<>();

 @BeforeEach
 public void beforeEach() throws Exception {
  injectionMap.put("securityEnabled", Boolean.TRUE);
 }

 @AfterEach
 public void afterEach() throws Exception {
  injectionMap.clear();
 }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.