2012-01-27 9 views
16

जब एक JUnit परीक्षण के भीतर से एक सेवा के एक संपत्ति नकली करने की कोशिश कर रहा समस्या हो रही है सेवा प्रॉक्सी:मजाक एक CGLIB की संपत्ति काम नहीं कर रहा

@ContextConfiguration("classpath:application-config.xml") 
@RunWith(SpringJUnit4ClassRunner.class) 
public class FooServiceTests { 

    @Autowired 
    private FooServiceImpl fooService; 

    @Test 
    public void testFoo() { 
     String str = fooService.foo(); 
     assertEquals("Var", str); 
    } 

    @Before 
    public void mockFooDao() throws Exception { 
     FooDao mockFooDao = Mockito.mock(FooDao.class); 
     Mockito.when(mockFooDao.foo()).thenReturn("Var"); 
     ReflectionTestUtils.setField(fooService, "fooDao", mockFooDao); 
    } 
} 

मजाक fooDao परिणाम के बाद से कोई प्रभाव नहीं है उम्मीद नहीं है। यहाँ दोनों सेवाओं और दाव का कोड है:

@Service("fooService") 
public class FooServiceImpl implements FooService { 

    @Autowired 
    protected FooDao fooDao; 

    @Override 
    public String foo() { 
     return fooDao.foo(); 
    } 
} 

@Repository 
public class FooDaoImpl implements FooDao { 

    @Override 
    public String foo() { 
     return "foo"; 
    } 
} 

हम देख सकते हैं वास्तविक सेवा "foo" वापसी करने के लिए है, लेकिन इतना सेवा देता है "var" परीक्षण दाव का मजाक उड़ाता है। मुझे पता है कि यह एक CGLIB प्रॉक्सी से संबंधित चीज है लेकिन मैं यह नहीं समझ सकता कि इसे फूडाओ संपत्ति के लिए एक सेटटर का उपयोग किए बिना कैसे काम करना है। किसी भी सहायता की सराहना की जाएगी।

सम्मान और अग्रिम धन्यवाद।

उत्तर

38

लघु जवाब

आप unwrap the proxy करने के लिए है और लक्ष्य वस्तु पर क्षेत्र सेट करें:

ReflectionTestUtils.setField(unwrapFooService(), "fooDao", mockFooDao); 

unwrapFooService() में परिभाषित किया जा सकता है:

private FooServiceImpl unwrapFooService() { 
    if(AopUtils.isAopProxy(fooService) && fooService instanceof Advised) { 
     Object target = ((Advised) fooService).getTargetSource().getTarget(); 
     return (FooServiceImpl)target; 
    } 
    return null; 
} 

... लंबे एक

समस्या काफी जटिल है, लेकिन इसलिए lvable। जैसा कि आपने अनुमान लगाया है कि यह सीजीआईएलबी प्रॉक्सी का दुष्प्रभाव है। सिद्धांत रूप में, वसंत का उप-वर्ग बनाता है जो FooServiceImpl$EnhancerByCGLIB के समान है। इस सबक्लास में संदर्भ मूल FooServiceImpl के साथ-साथ ... सभी फ़ील्ड FooServiceImpl में है (जो समझ में आता है - यह सबक्लास है)।

तो वास्तव में दो चर हैं: FooServiceImpl$EnhancerByCGLIB.fooDao और FooServiceImpl.fooDao। आप पूर्व में एक नकली असाइन कर रहे हैं लेकिन आपकी सेवा बाद में उपयोग करती है ... मैं wrote कुछ समय पहले इस समस्या के बारे में।

+0

हाँ! इसने काम कर दिया! बहुत बहुत धन्यवाद Tomasz। – franDayz

+0

@ frandiaz83: खुशी है कि मैं मदद कर सकता हूँ! [स्वीकृति] पर विचार करें (http://meta.stackexchange.com/questions/5421) और/या उचित समाधान के लिए भावी पाठकों को इंगित करने के लिए सही उत्तर को ऊपर उठाना। –

+0

हां, ज़ाहिर है। मैंने जवाब स्वीकार कर लिया है लेकिन मैं वोट नहीं दे सकता क्योंकि मेरे पास पर्याप्त प्रतिष्ठा नहीं है ... धन्यवाद। – franDayz

संबंधित मुद्दे