2013-04-29 6 views
10

मैं केक पैटर्न को अपनाने की कोशिश कर रहा हूं लेकिन मुझे इस प्रोग्रामिंग शैलियों का अनुकूलन करने में कठिनाई हो रही है, खासकर जहां यूनिट परीक्षणों का संबंध है।स्कैला: मॉकिंग और केक पैटर्न

trait Vet { 
    def vaccinate(pet: Pet) 
} 

trait PetStore { this: Vet => 
    def sell(pet: Pet) { 
    vaccinate(pet) 
    // do some other stuff 
    } 
} 

अब, मैं जबकि वेट से कार्यों को मजाक petstore परीक्षण करना चाहते हैं:

मान मैं निम्नलिखित व्यापार वस्तुओं है कि सुविधा देता है। अगर मैं संरचना का उपयोग कर रहा था, तो मैं एक नकली [वेट] बना रहा था और इसे पेटस्टोर कन्स्ट्रक्टर में पास कर रहा था, फिर जावा दुनिया में जैसे मॉक प्रोग्रामिंग कर रहा था। हालांकि, मुझे कोई संदर्भ नहीं मिल रहा है कि लोग केक पैटर्न के साथ ऐसा कैसे करते हैं।

एक संभावित समाधान अपेक्षित उपयोग के अनुसार प्रत्येक टेस्ट केस पर टीकाकरण() लागू करना होगा, लेकिन यह मुझे यह सत्यापित करने की अनुमति नहीं देता है कि मैक्स को ठीक से बुलाया गया था, मुझे मैचर्स का उपयोग करने की अनुमति नहीं देता है, आदि

तो - लोग नकली पैटर्न के साथ केक पैटर्न का उपयोग कैसे कर रहे हैं?

उत्तर

6

मैंने इस ब्लॉग पोस्ट को पढ़ने के बाद केक पैटर्न का उपयोग करना शुरू किया: https://github.com/precog/staticsite/blob/master/contents/blog/Existential-Types-FTW/index.md यह दृष्टिकोण स्वयं के प्रकारों के बजाय उस अस्तित्व-प्रकारों में अधिकांश केक पैटर्न पोस्ट से अलग है।

मैं कुछ महीनों के लिए इस पैटर्न का उपयोग कर रहा हूं और ऐसा लगता है कि जब मैं चाहता हूं तो मैं एक नकली निर्दिष्ट कर सकता हूं। इसमें अधिक निर्भरता इंजेक्शन महसूस होता है, लेकिन इसमें आपके कोड को गुणों में रखने के सभी लाभ होते हैं।

अस्तित्व-प्रकार का उपयोग कर अपनी समस्या का मेरे bastardized संस्करण कुछ इस तरह होगा:

case class Pet(val name: String) 
trait ConfigComponent { 
    type Config 
    def config: Config 
} 

trait Vet { 
    def vaccinate(pet: Pet) = {println ("Vaccinate:" + pet)} 
} 

trait PetStoreConfig { 
    val vet: Vet 
} 
trait PetStore extends ConfigComponent { 

    type Config <: PetStoreConfig 

    def sell(pet: Pet) { 
     config.vet.vaccinate(pet) 
     // do some other stuff 
    } 
} 

आप अपने ऐप

class MyApp extends PetStore with PetStoreConfig { 

    type Config = MyApp 
    def config = this 

    val vet = new Vet{} 
    sell(new Pet("Fido")) 

} 

scala> new MyApp 
Vaccinate:Pet(Fido) 
res0: MyApp = [email protected] 

में एक साथ यह सब रख सकते हैं और अगर आप घटकों को व्यक्तिगत परीक्षण कर सकते हैं VetLike का एक उदाहरण बनाकर और VetLike का एक नकली बनाकर इसे अपने पेटस्टोर परीक्षण का उपयोग करके।

//Test VetLike Behavior 
scala> val vet = new Vet{} 
scala> vet.vaccinate(new Pet("Fido")) 
Vaccinate:Pet(Fido) 


//Test Petstore Behavior 

class VetMock extends Vet { 
    override def vaccinate(pet: Pet) = println("MOCKED") 
} 

class PetStoreTest extends PetStore with PetStoreConfig { 
    type Config = PetStoreTest 
    def config = this 

    val vet = new VetMock 
    val fido = new Pet("Fido") 
    sell(fido) 
} 

scala> new PetStoreTest 
MOCKED 
+0

यह अच्छा है - लेकिन क्या मुझे कुछ याद आ रहा है? आप पेटस्टोर में वीट प्रकार के साथ क्या कर रहे हैं? –

+0

तो मैंने ConfigComponent विशेषता का उपयोग किए बिना एक उदाहरण देने की कोशिश की, लेकिन मैं था कुछ गलत कर रहा हूँ वैसे भी, मैंने इस उदाहरण को अद्यतन किया है और ConfigComponent जोड़ा है। उम्मीद है कि चीजें थोड़ा और स्पष्ट दिखती हैं। Https://www.precog.com/blog/Existential-Types-FTW/ के लिए – OleTraveler

+0

+1 –

4

यह एक अच्छा सवाल है। हम निष्कर्ष पर पहुंचे कि यह नहीं किया जा सकता है, कम से कम उसी तरह से नहीं जिसे हम उपयोग करते हैं। मोक्स के बजाय स्टब्स का उपयोग करना और केक के अनुसार स्टब्स मिश्रण करना संभव है। लेकिन यह मोजे का उपयोग करने से ज्यादा काम है।

हमारे पास दो स्कैला टीम हैं और एक टीम ने मोक्स के बजाय स्टब्स का उपयोग करके केक पैटर्न को अपनाया है, जबकि दूसरी टीम कक्षाओं और निर्भरता इंजेक्शन पर फंस गई है। अब मैंने दोनों की कोशिश की है, मैं परीक्षण के लिए आसान होने के कारण मैं मोक्स के साथ DI पसंद करते हैं। और भी पढ़ने के लिए तर्कसंगत सरल है।

+1

लिखने के समय यह शुरू में मेरे विचार था पर शीर्ष जवाब था पीछा किया। हालांकि के रूप में मैं स्काला के साथ अधिक से अधिक काम शुरू कर दिया है, मैं करने के लिए मिल गया है मंच जहां मैं एक ही वैचारिक व्यावसायिक वस्तुओं की अलग-अलग चिंताओं को अलग-अलग गुणों से अलग कर रहा हूं, टेस्टेबिलिटी और स्पष्टता उद्देश्यों के लिए अलग-अलग लक्षणों के लिए। यहां डीआई का उपयोग करने से अत्यधिक बड़े ऑब्जेक्ट ग्राफ और बोझिल एप्लिकेशन प्रारंभिक कोड का कारण बन जाएगा। –

+0

वाईएमएमवी जैसा कि वे कहते हैं। हमारा अनुभव विपरीत था –

2

मुझे यूनिट परीक्षण 'केक पैटर्न' मॉड्यूल के उद्देश्य के लिए स्केलेटेस्ट के साथ स्कैलेमॉक का उपयोग करने का एक तरीका मिला है।

सबसे पहले, मुझे कई समस्याएं थीं (this एक सहित), लेकिन मेरा मानना ​​है कि नीचे दिया गया समाधान स्वीकार्य है। यदि आपको कोई चिंता है, तो कृपया मुझे बताएं।

trait VetModule { 
    def vet: Vet 
    trait Vet { 
    def vaccinate(pet: Pet) 
    } 
} 

trait PetStoreModule { 
    self: VetModule => 
    def sell(pet: Pet) 
} 

trait PetStoreModuleImpl extends PetStoreModule { 
    self: VetModule => 
    def sell(pet: Pet) { 
    vet.vaccinate(pet) 
    // do some other stuff 
    } 
} 

परीक्षण उसके बाद निम्न रूप में परिभाषित कर रहे हैं:

यह कैसे मैं अपने उदाहरण डिजाइन होता है

class TestPetstore extends FlatSpec with ShouldMatchers with MockFactory { 

    trait PetstoreBehavior extends PetStoreModule with VetModule { 

    object MockWrapper { 
     var vet: Vet = null 
    } 

    def fixture = { 
     val v = mock[Vet] 
     MockWrapper.vet = v 
     v 
    } 

    def t1 { 
     val vet = fixture 
     val p = Pet("Fido") 
     (vet.vaccinate _).expects(p) 
     sell(p) 
    } 

    def vet: Vet = MockWrapper.vet 
    } 

    val somePetStoreImpl = new PetstoreBehavior with PetStoreModuleImpl 
    "The PetStore" should "vaccinate an animal before selling" in somePetStoreImpl.t1 
} 

इस स्थापना का उपयोग करना, आप 'नुकसान' आप कॉल करने के लिए है कि है आपके द्वारा लिखे गए प्रत्येक परीक्षण में val vet = fixture। दूसरी ओर, एक आसानी से एक और परीक्षण की 'कार्यान्वयन',

val someOtherPetStoreImpl = new PetstoreBehavior with PetStoreModuleOtherImpl 
1

बना सकते हैं उदाहरण के लिए, हालांकि यह एक पुराने सवाल है, मैं भविष्य पाठकों के लिए मेरा उत्तर जोड़ रहा। मुझे विश्वास है कि यह SO पोस्ट - How to use mocks with the Cake Pattern - एक ही चीज़ पूछता है और जवाब देता है।

मैं सफलतापूर्वक जवाब व्लादिमीर Matveev द्वारा दिए गए (जो

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