كيف ينبغي أن وحدة الاختبارات إنشاء مصادر البيانات عندما لا تكون قيد التشغيل في تطبيق الخادم ؟

StackOverflow https://stackoverflow.com/questions/831760

سؤال

شكرا لكم جميعا على مساعدتكم.عدد من نشر (كما يجب أن يكون من المتوقع) إجابات مشيرا إلى بلدي النهج كله كان خطأ ، أو أن مستوى منخفض رمز ينبغي أبدا أن تعرف ما إذا كان أو لم يكن يعمل في وعاء.أنا أميل إلى الاتفاق.ومع ذلك, أنا أتعامل مع مجمع تراث التطبيق وليس لديهم خيار تقوم بعمل إعادة بيع ديون على المشكلة الحالية.

اسمحوا لي أن خطوة الى الوراء طرح السؤال دوافع سؤالي.

لدي إرث التطبيق يعمل تحت جبوس ، جعلت بعض التعديلات على مستوى أقل التعليمات البرمجية.لقد خلق وحدة اختبار بلدي التعديل.من أجل تشغيل الاختبار ، أحتاج إلى الاتصال بقاعدة بيانات.

إرث رمز يحصل على مصدر البيانات بهذه الطريقة:

(jndiName هو تعريف سلسلة)

Context ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup(jndiName);

مشكلتي هي عند تشغيل هذه التعليمات البرمجية في إطار وحدة اختبار سياق لا يوجد لديه مصادر البيانات المحددة.الحل لهذا هو محاولة لمعرفة ما إذا أنا على التوالي في ظل تطبيق الخادم ، إن لم يكن إنشاء اختبار البيانات وإعادتها.إذا أنا على التوالي في إطار التطبيق الملقم ثم يمكنني استخدام رمز أعلاه.

لذلك ، الحقيقي السؤال هو:ما هي الطريقة الصحيحة للقيام بذلك ؟ هناك بعض المعتمدة طريقة اختبار وحدة يمكن تعيين ما يصل السياق إلى عودة المناسبة مصدر البيانات بحيث رمز تحت الاختبار لا تحتاج إلى أن تكون على علم من أين يعمل ؟


السياق:سؤالي:

لدي بعض جافا البرمجية التي تحتاج إلى معرفة ما إذا كان أو لم يكن هو يعمل تحت جبوس.هل هناك الكنسي طريقة كود لمعرفة ما إذا كان يعمل في الحاوية ؟

أول النهج المتقدمة من خلال experimention ويتكون من الحصول على الأولية سياق التجارب أنه يمكن البحث عن قيم معينة.

private boolean isRunningUnderJBoss(Context ctx) {
        boolean runningUnderJBoss = false;
        try {
            // The following invokes a naming exception when not running under
            // JBoss.
            ctx.getNameInNamespace();

            // The URL packages must contain the string "jboss".
            String urlPackages = (String) ctx.lookup("java.naming.factory.url.pkgs");
            if ((urlPackages != null) && (urlPackages.toUpperCase().contains("JBOSS"))) {
                runningUnderJBoss = true;
            }
        } catch (Exception e) {
            // If we get there, we are not under JBoss
            runningUnderJBoss = false;
        }
        return runningUnderJBoss;
    }

Context ctx = new InitialContext();
if (isRunningUnderJboss(ctx)
{
.........

الآن يبدو أن هذا العمل ، لكنه يشعر مثل هاك.ما هو "الصحيح" طريقة للقيام بذلك ؟ من الناحية المثالية, أحب الطريقة التي سوف تعمل مع مجموعة متنوعة من خوادم التطبيق ليس فقط جبوس.

هل كانت مفيدة؟

المحلول

النهج كله شعور خاطئ توجهت لي.إذا كان التطبيق الخاص بك يحتاج إلى معرفة أي حاوية انها تعمل في كنت تفعل شيئا خاطئا.

عند استخدام الربيع أنا يمكن أن تتحرك من هر إلى يبلوغيتش والعودة دون تغيير أي شيء.أنا متأكد أنه مع التكوين الصحيح أنني يمكن أن تفعل نفس الحيلة مع جبوس كذلك.هذا هو الهدف أود أن تبادل لاطلاق النار.

نصائح أخرى

وهذا المفهوم كله هو الخلف إلى الأمام. رمز مستوى أدنى لا ينبغي أن يفعل هذا النوع من التجارب. إذا كنت في حاجة الى تنفيذ مختلف تمر عليه في نقطة ذات الصلة.

ووبعض مزيج من التبعية حقن (سواء من خلال الربيع وملفات التكوين، أو الحجج البرنامج) ونمط مصنع تعمل عادة أفضل.

وكمثال على ذلك أمرر حجة لكتاباتي النملة أن ملفات الإعداد التكوين تبعا إذا الأذن أو الحرب تسير في التطوير والاختبار، أو بيئة الإنتاج.

ولعل شيئا من هذا القبيل (قبيحة ولكنها قد تعمل)

 private void isRunningOn( String thatServerName ) { 

     String uniqueClassName = getSpecialClassNameFor( thatServerName );
     try { 
         Class.forName( uniqueClassName );
     } catch ( ClassNotFoudException cnfe ) { 
         return false;
     }
     return true;
 } 

و <م> getSpecialClassNameFor طريقة سيعود فئة التي هي فريدة من نوعها لكل ملقم التطبيق (وقد ترجع أسماء فئة جديدة عند إضافة خوادم المزيد من التطبيقات)

وبعد ذلك يمكنك استخدامه مثل:

  if( isRunningOn("JBoss")) {
         createJBossStrategy....etcetc
  }
<اقتباس فقرة>
Context ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup(jndiName);

من يبني InitialContext؟ يجب أن يكون بنائه خارج التعليمات البرمجية التي تحاول اختبار، أو وإلا فإنك لن تكون قادرا على السخرية من السياق.

وبما انك ذكرت أنك تعمل على تطبيق إرث، أول ريفاكتور رمز بحيث يمكنك بسهولة التبعية حقن السياق أو مصدر البيانات إلى الفئة. ثم يمكنك بسهولة كتابة الاختبارات لتلك الفئة.

ويمكنك الانتقال رمز إرث من وجود اثنين من الصانعين، كما في التعليمات البرمجية أدناه، حتى يكون لديك ريفاكتوريد الرمز الذي يبني الطبقة. وبهذه الطريقة يمكنك اختبار أكثر سهولة فو وتتمكن من الحفاظ على التعليمات البرمجية التي تستخدم فو دون تغيير. ثم يمكنك ريفاكتور ببطء رمز، بحيث منشئ القديم هو إزالتها بالكامل وكافة التبعيات حقن التبعية.

public class Foo {
  private final DataSource dataSource;
  public Foo() { // production code calls this - no changes needed to callers
    Context ctx = new InitialContext();
    this.dataSource = (DataSource) ctx.lookup(jndiName);
  }
  public Foo(DataSource dataSource) { // test code calls this
    this.dataSource = dataSource;
  }
  // methods that use dataSource
}

ولكن قبل أن تبدأ في فعل ذلك إعادة بيع ديون، يجب أن يكون لديك بعض الاختبارات التكامل لتغطية ظهرك. وإلا لا يمكنك معرفة ما إذا كان حتى refactorings بسيطة مثل تحريك بحث مصدر البيانات إلى منشئ، كسر شيء. ثم عندما يحصل على كود أفضل وأكثر قابلة للاختبار، يمكنك كتابة وحدة الاختبارات. (بحكم التعريف، إذا كان اختبار يمس نظام الملفات، شبكة أو قاعدة بيانات، فإنه ليس وحدة الاختبار - وهو اختبار التكامل)

والاستفادة من وحدة الاختبارات هو أنها تشغيل سريع - مئات أو آلاف في الثانية - ومركزة جدا لاختبار سلوك واحد فقط في المرة الواحدة. وهذا يجعل من الممكن تشغيل ثم في كثير من الأحيان (إذا كنت أتردد اجراء جميع الفحوصات وحدة بعد تغيير سطر واحد، أنها تعمل ببطء شديد) حتى يتسنى لك الحصول على ردود فعل سريعة. ولأنها مركزة جدا، وسوف تعرف فقط من خلال النظر في اسم اختبار إذا تعذر ذلك بالضبط مكان في رمز الإنتاج علة هو.

والاستفادة من تجارب التكامل هو أنها التأكد من أن جميع أجزاء موصولة معا بشكل صحيح. وهذا هو أيضا مهم، ولكن لا يمكنك تشغيلها في كثير من الأحيان لأن الأمور مثل لمس قاعدة بيانات جعلها بطيئة جدا. ولكن يجب أن لا تزال تشغيلها مرة واحدة على الأقل في اليوم على خادم التكامل المستمر الخاص بك.

وهناك عدة طرق لمعالجة هذه المشكلة. واحد هو لتمرير كائن السياق إلى فئة عندما يكون تحت الاختبار وحدة. إذا كنت لا تستطيع تغيير توقيع الأسلوب، ريفاكتور خلق سياق inital إلى طريقة المحمية واختبار فئة فرعية تقوم بإرجاع كائن سياق سخر من تجاوز الأسلوب. التي يمكن على الأقل وضع الطبقة تحت الاختبار حتى تتمكن من ريفاكتور إلى بدائل أفضل من هناك.

والخيار التالي هو لإجراء اتصالات قاعدة بيانات مصنع يمكن أن نقول إذا كان في وعاء أو لا، وفعل الشيء المناسب في كل حالة.

وشيء واحد للتفكير و- مرة واحدة لديك اتصال قاعدة البيانات خارج الحاوية، ما الذي تنوي القيام به حيال ذلك؟ ومن الأسهل، لكنها ليست واردة وحدة الاختبار إذا كان لديك للقيام طبقة الوصول إلى البيانات بأكملها.

لمزيد من المساعدة في هذا الاتجاه لنقل الشفرة القديمة تحت الاختبار وحدة، أقترح عليك أن ننظر مايكل الريشة <لأ href = "https://rads.stackoverflow.com/amzn/click/com/0131177052" يختلط = " نوفولو noreferrer "> العمل على نحو فعال مع رمز تراث .

وهناك طريقة نظيفة للقيام بذلك سيكون لديك المستمعين دورة تكوين في web.xml. ويمكن لهذه مجموعة الأعلام العالمية إذا كنت تريد. على سبيل المثال، يمكنك تعريف ServletContextListener في web.xml وفي طريقة contextInitialized، تعيين إشارة العالمي الذي كنت تعمل داخل وعاء. إذا لم يتم تعيين علامة العمومية، ثم كنت لا تشغل داخل الحاوية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top