परीक्षण - इन-मेमोरी डीबी बनाम मॉकिंग


12

परीक्षण लिखते समय, कोई व्यक्ति केवल डेटा को मॉक करने पर इन-मेमोरी डेटाबेस का उपयोग क्यों करना चाहेगा?

मैं देख सकता हूं कि किसी के रिपॉजिटरी के परीक्षण के लिए इन-मेमोरी डेटाबेस फायदेमंद हो सकता है। लेकिन अगर एक फ्रेमवर्क (जैसे स्प्रिंग डेटा) का उपयोग किया जाता है, तो रिपॉजिटरी का परीक्षण फ्रेमवर्क का परीक्षण करेगा और वास्तव में एप्लिकेशन लॉजिक नहीं।

मॉकिंग, हालांकि, तेज लगता है और उसी पैटर्न का अनुसरण करता है जो आमतौर पर इकाई परीक्षण और टीडीडी लिखते समय नियोजित होता है।

तो मुझे क्या याद आ रही है? जब / इन-मेमोरी डेटाबेस क्यों फायदेमंद होगा?

जवाबों:


14

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

लेकिन अगर एक फ्रेमवर्क (जैसे स्प्रिंग डेटा) का उपयोग किया जाता है, तो रिपॉजिटरी का परीक्षण फ्रेमवर्क का परीक्षण करेगा और वास्तव में एप्लिकेशन लॉजिक नहीं।

एक वास्तविक डेटाबेस का उपयोग करके आप परीक्षण कर रहे हैं कि आप वास्तव में सही तरीके से कॉन्फ़िगरेशन और उपयोग कर रहे हैं। इसके अलावा फ्रेमवर्क में कमियां हो सकती हैं जो केवल वास्तविक डेटाबेस के साथ परीक्षण करते समय ही सामने आती हैं (उदाहरण के लिए: स्प्रिंग डेटा पोस्टग्रेक्यूएल के संस्करण 9.2 का समर्थन नहीं करता है)।

मैं अपने अधिकांश परीक्षण कवरेज को नकली स्रोतों के खिलाफ लिखूंगा, लेकिन मैं एक वास्तविक डेटाबेस का उपयोग करके आमतौर पर प्रयोग किए जाने वाले मामलों के लिए कुछ अंत-से-अंत परीक्षण लिखूंगा।


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

2

अधिकांश समय, इन-मेमोरी डेटाबेस परीक्षण मॉकिंग की तुलना में सरल होता है। यह और भी अधिक लचीला है। और यह भी परीक्षण करता है कि माइग्रेशन फाइलें अच्छी तरह से की जाती हैं (जब माइग्रेशन फाइलें होती हैं)।

इस छद्म कोड को देखें:

class InMemoryTest 
{
    /** @test */
    public function user_repository_can_create_a_user()
    {
        $this->flushDatabase();

        $userRepository = new UserRepository(new Database());
        $userRepository->create('name', 'email@email.com');

        $this->seeInDatabase('users', ['name' => 'name', 'email' => 'email@email.com']);
    }
}

class MockingDBTest
{
    /** @test */
    public function user_repository_can_create_a_user()
    {
        $databaseMock = MockLib::mock(Database::class);
        $databaseMock->shouldReceive('save')
                     ->once()
                     ->withArgs(['users', ['name' => 'name', 'email' => 'email@email.com']]);

        $userRepository = new UserRepository($databaseMock);
        $userRepository->create('name', 'email@email.com');
    }
}

यह इस InMemoryTestबात पर निर्भर नहीं करता है कि कैसे काम Databaseमें लागू किया UserRepositoryजाता है। यह बस UserRepositoryसार्वजनिक इंटरफ़ेस ( create) का उपयोग करता है और फिर इसके खिलाफ दावा करता है। यदि आप कार्यान्वयन को बदलते हैं तो यह परीक्षा नहीं टूटेगी लेकिन यह धीमी है।

इस बीच, MockingDBTestकैसे Databaseलागू किया जाता है पर पूरी तरह से निर्भर करता है UserRepository। वास्तव में, यदि आप कार्यान्वयन को बदलते हैं, लेकिन फिर भी इसे दूसरे तरीके से काम करते हैं, तो यह परीक्षा टूट जाएगी।

दोनों दुनिया के सर्वश्रेष्ठ इंटरफ़ेस को लागू करने वाले नकली का उपयोग करेंगे Database:

class UsingAFakeDatabaseTest
{
    /** @test */
    public function user_repository_can_create_a_user()
    {
        $fakeDatabase = new FakeDatabase();
        $userRepository = new UserRepository($fakeDatabase);
        $userRepository->create('name', 'email@email.com');

        $this->assertEquals('name', $fakeDatabase->datas['users']['name']);
        $this->assertEquals('email@email.com', $fakeDatabase->datas['users']['email']);
    }
}

interface DatabaseInterface
{
    public function save(string $table, array $datas);
}

class FakeDatabase implements DatabaseInterface
{
    public $datas;

    public function save(string $table, array $datas)
    {
        $this->datas[$table][] = $datas;
    }
}

यह अधिक अभिव्यंजक है, पढ़ने में आसान और समझने में आसान है, और यह कोड की उच्च परतों में किए गए वास्तविक डेटाबेस के कार्यान्वयन पर निर्भर नहीं करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.