डेटा एक्सेस लेयर का परीक्षण कैसे करें?


17

मेरे पास एक DAO तरीका है जो JDBC एक्सेस के लिए स्प्रिंग का उपयोग करता है। यह एक विक्रेता के आइटम की बिक्री की सफलता दर की गणना करता है।

यहाँ कोड है:

public BigDecimal getSellingSuccessRate(long seller_id) {
    String sql = "SELECT SUM(IF(sold_price IS NOT NULL, 1, 0))/SUM(1) 
                  FROM transaction WHERE seller_id = ?";
    Object[] args = {seller_id};
    return getJdbcTemplate().queryForObject(sql, args, BigDecimal.class);
}

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


DBUnit की जाँच करें । यह आपकी समस्या को हल करने के लिए विशेष रूप से बनाया गया है।
सर्जियो

जवाबों:


15

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

डेटाबेस का मजाक उड़ाना एक विकल्प है, लेकिन यह वास्तविक प्रश्नों का परीक्षण नहीं करता है। यह एक बहुत ही सरल समाधान के रूप में इस्तेमाल किया जा सकता है जब आप सुनिश्चित करना चाहते हैं कि डीएओ से डेटा ठीक से सिस्टम से गुजरता है। लेकिन स्वयं DAO के परीक्षण के लिए आपको DAO के पीछे कुछ चाहिए होता है, जिसमें डेटा और प्रश्न ठीक से चलते हैं।

पहली बात यह है कि स्मृति डेटाबेस में एक का उपयोग करें। हाइपरएसडी इसके लिए एक उत्कृष्ट विकल्प है क्योंकि इसमें किसी अन्य डेटाबेस की बोली का अनुकरण करने की क्षमता है - ताकि डेटाबेस के बीच मामूली अंतर समान हो (डेटा प्रकार, फ़ंक्शन और इसी तरह)। hsqldb में यूनिट टेस्टिंग के लिए कुछ अच्छे फीचर्स भी हैं।

db.url=jdbc:hsqldb:file:src/test/resources/testData;shutdown=true;

यह testDataफ़ाइल से डेटाबेस (तालिकाओं, प्रारंभिक डेटा) की स्थिति को लोड करता है । shutdown=trueअंतिम कनेक्शन बंद होने पर स्वचालित रूप से डेटाबेस को बंद कर देगा।

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

आपका DAO तब इंजेक्ट किए गए डेटाबेस का उपयोग करता है जिसके लिए आप डेटाबेस के विरुद्ध परीक्षण शुरू कर सकते हैं।

इकाई परीक्षण तब कुछ ऐसे दिखेंगे जैसे (उबाऊ सामान जो कि संक्षिप्तता के लिए शामिल नहीं है):

    @Before
    public void setUpDB() {
        DBConnection connection = new DBConnection();
        try {
            conn = connection.getDBConnection();
            insert = conn.prepareStatement("INSERT INTO data (txt, ts, active) VALUES (?, ?, ?)");
        } catch (SQLException e) {
            e.printStackTrace();
            fail("Error instantiating database table: " + e.getMessage());
        }
    }

    @After
    public void tearDown() {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private void addData(String txt, Timestamp ts, boolean active) throws Exception {
        insert.setString(1, txt);
        insert.setTimestamp(2, ts);
        insert.setBoolean(3, active);
        insert.execute();
    }

    @Test
    public void testGetData() throws Exception {
        // load data
        Calendar time = Calendar.getInstance();
        long now = time.getTimeInMillis();
        long then1h = now - (60 * 60 * 1000);  // one hour ago
        long then2m = now - (60 * 1000 * 2);   // two minutes ago
        addData("active_foo", new Timestamp(then1h), true);     // active but old
        addData("inactive_bar", new Timestamp(then1h), false);  // inactive and old
        addData("active_quz", new Timestamp(then2m), true);     // active and new
        addData("inactive_baz", new Timestamp(then2m), false);  // inactive and new

        DataAccess dao = new DataAccess();
        int count = 0;
        for (Data data : dao.getData()) {
            count++;
            assertTrue(data.getTxt().startsWith("active"));
        }

        assertEquals("got back " + count + " rows instead of 1", count, 1);
    }

और इस प्रकार, आपको एक इकाई परीक्षण मिला है जो डीएओ को कॉल करता है और उस डेटा का उपयोग कर रहा है जो परीक्षण की अवधि के लिए मौजूद फ्लाई डेटाबेस पर स्थापित किया गया था। रन से पहले आपको बाहरी संसाधनों या डेटाबेस की स्थिति के बारे में चिंता करने की ज़रूरत नहीं है, या किसी ज्ञात स्थिति में पुनर्स्थापित करना (ठीक है, 'ज्ञात राज्य' 'अस्तित्व में नहीं है' जो कि वापस लौटने के लिए तुच्छ है)।

DBUnit डेटाबेस बनाने में, टेबल बनाने और डेटा लोड करने में एक सरल प्रक्रिया का वर्णन करता है। यदि आपको किसी कारण से वास्तविक डेटाबेस का उपयोग करने की आवश्यकता है, तो यह उपयोग करने के लिए बेहतर उपकरण है।

उपरोक्त कोड एक मैवेन परियोजना का हिस्सा है जिसे मैंने अवधारणा परीक्षण के प्रमाण के लिए लिखा था


2
मैं उस हिस्से के बारे में नहीं जानता था जो HSQL दूसरे db विक्रेता की बोली का मजाक उड़ा सकता है। धन्यवाद।
माइकल

1
@ यह डेटाबेस गुणों के माध्यम से किया जा सकता है, जैसे कि sql.syntax_mys=truehsqldb के काम करने के तरीके में बदलाव होता है: "यह गुण, जब सही होता है, TEXT और AUTO_INCREMENT प्रकारों के लिए समर्थन सक्षम करता है और इस बोली के कुछ अन्य पहलुओं के साथ अनुकूलता की अनुमति देता है।" जबकि sql.syntax_ora=true"यह संपत्ति, जब सही सेट किया जाता है, गैर-मानक प्रकारों के लिए समर्थन सक्षम करता है। यह DUAL, ROWNUM, NEXTVAL और CURRVAL वाक्यविन्यास को भी सक्षम बनाता है और इस बोली के कुछ अन्य पहलुओं के साथ संगतता की अनुमति देता है।"

DBUnit तरीका है :)
सिल्वियु बर्किया

@SilviuBurcea DBUnit निश्चित रूप से एक जटिल डेटाबेस परीक्षण वातावरण स्थापित करने की 'प्लंबिंग' को हाथ से करने की तुलना में बहुत आसान बनाता है। यह अब भी कभी-कभी यह जानने के लिए उपयोगी होता है कि इसे कैसे किया जाए यदि आपको ज़रूरत है (उपर्युक्त उल्लिखित 'बाय हैंड' दृष्टिकोण को अन्य भाषाओं में माइग्रेट किया जा सकता है जहाँ DBUnit कोई विकल्प नहीं है)।

आप पर एक नज़र हो सकता है अनुचर
cchantep

2

सबसे पहले, आपको उत्पादन वातावरण में परीक्षण कभी नहीं करना चाहिए। आपके पास एक परीक्षण वातावरण होना चाहिए जो आपके उत्पादन वातावरण को प्रतिबिंबित करता है और वहां एकीकरण परीक्षण करता है।

यदि आप ऐसा करते हैं, तो आप कई काम कर सकते हैं।

  • इकाई परीक्षण लिखें जो यह देखने के लिए परीक्षण करते हैं कि क्या मॉकिटो जैसे मॉकिंग फ्रेमवर्क का उपयोग करके एक मॉक आइटम के लिए उपयुक्त एसक्यूएल प्रस्तुत किया जा रहा है। यह सुनिश्चित करेगा कि आपका तरीका वही कर रहा है जो उसे करना है और तस्वीर से एकीकरण लेता है।
  • अपने यूनिट परीक्षणों में आपके द्वारा परीक्षण किए गए SQL की उपयुक्तता का प्रदर्शन करते हुए परीक्षण SQL स्क्रिप्ट लिखें। यह आपके द्वारा आने वाले किसी भी ट्यूनिंग मुद्दों के साथ मदद कर सकता है, जैसा कि आप अपने परीक्षण लिपियों के आधार पर व्याख्या और ऐसे भी चला सकते हैं।
  • DBUnit का उपयोग करें, जैसा कि @Sergio द्वारा उल्लेख किया गया है।

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

1

हमारी परियोजना पर, प्रत्येक डेवलपर एक खाली डेटाबेस चला रहा है, इसकी संरचना उत्पादन डेटाबेस के समान है।

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

इस तरह, sql लेयर का परीक्षण करना संभव है। वास्तव में, प्रत्येक क्वेरी या डेटाबेस कॉल को इस तरह से परीक्षण करना होगा।

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


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

पहले ऐसा करने के लिए कभी नहीं सोचा था। हमारे परीक्षणों में, अधिकांश परीक्षण एक उपयोगकर्ता 'x' बनाते हैं, जो अद्वितीय है। एक बार db बनाने का मतलब उन वस्तुओं के पुन: उपयोग के लिए परीक्षणों को बदलना होगा।
कार्रा

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

यह सही है, आदेश तब कोई फर्क नहीं पड़ता। हमने देखा है कि परीक्षण पहले विफल हो गए क्योंकि यूनिट टेस्ट रन ऑर्डर हमारे बिल्ड पीसी और हमारे स्थानीय मशीन पर अलग है।
कार्रा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.