سؤال

ولدي رمز إرث التالية:

public class MyLegacyClass
{
    private static final String jndiName = "java:comp/env/jdbc/LegacyDataSource"

    public static SomeLegacyClass doSomeLegacyStuff(SomeOtherLegacyClass legacyObj)
    {
       // do stuff using jndiName
    }
}

وهذه الفئة تعمل في J2EE حاوية.

والآن أود أن اختبار خارج الطبقة الحاوية.

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

والوصول يسمح للLegacyDataSource (الاختبار ليس من الضروري أن تكون "نقية" وحدة للتجارب).

وتحرير: لدى تقديمه-الأطر وقت التشغيل إضافية غير مسموح به

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

المحلول

وفقط لجعل @ اقتراح روبن من نمط استراتيجية أكثر واقعية: (لاحظ أن API العام من سؤالك الأصلي لم يتغير)

public class MyLegacyClass {

  private static Strategy strategy = new JNDIStrategy();

  public static SomeLegacyClass doSomeLegacyStuff(SomeOtherLegacyClass legacyObj) {
    // legacy logic
    SomeLegacyClass result = strategy.doSomeStuff(legacyObj);
    // more legacy logic
    return result;
  }

  static void setStrategy(Strategy strategy){
    MyLegacyClass.strategy = strategy;
  }

}

interface Strategy{
  public SomeLegacyClass doSomeStuff(SomeOtherLegacyClass legacyObj);
}

class JNDIStrategy implements Strategy {
  private static final String jndiName = "java:comp/env/jdbc/LegacyDataSource";

  public SomeLegacyClass doSomeStuff(SomeOtherLegacyClass legacyObj) {
    // do stuff using jndiName
  }
}

... واختبار أداة JUnit. أنا لست مروحة كبيرة من الحاجة إلى القيام بذلك صيانة الإعداد / teardown، ولكن هذا له تأثير الجانب المؤسف من وجود API على أساس أساليب ثابتة (أو الأوراق الوحيدة في هذا الشأن). ما أنا <م> قيام عن مثل هذا الاختبار هو أنه لا يستخدم JNDI - هذا امر جيد لأن (أ) أنها سوف تعمل بسرعة، و (ب) اختبار وحدة يجب فقط أن يختبر منطق الأعمال في doSomeLegacyStuff ( ) طريقة على أي حال، وليس اختبار مصدر البيانات الفعلية. (بالمناسبة، هذا يفترض الطبقة الاختبار في نفس الحزمة كما MyLegacyClass).

public class MyLegacyClassTest extends TestCase {

  private MockStrategy mockStrategy = new MockStrategy();

  protected void setUp() throws Exception {
    MyLegacyClass.setStrategy(mockStrategy);
  }

  protected void tearDown() throws Exception {
    // TODO, reset original strategy on MyLegacyClass...
  }

  public void testDoSomeLegacyStuff() {
    MyLegacyClass.doSomeLegacyStuff(..);
    assertTrue(..);
  }

  static class MockStrategy implements Strategy{

    public SomeLegacyClass doSomeStuff(SomeOtherLegacyClass legacyObj) {
      // mock behavior however you want, record state however
      // you'd like for test asserts.  Good frameworks like Mockito exist
      // to help create mocks
    }
  }
}

نصائح أخرى

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

في هذه الحالة، يمكنك حقن مصدر البيانات الخاص بك.

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

وأعتقد أن الحل الأمثل هنا هو ربط ذلك JNDI إلى محلي

وقانون الإرث يستخدم jndiName مثل ما يلي:

DataSource datasource = (DataSource)initialContext.lookup(DATASOURCE_CONTEXT);

وهكذا، وربط الحل هنا محلية (أو أيا كان لديك لك اختبار البيانات) في JNDI مثل ما يلي:

  BasicDataSource dataSource = new BasicDataSource();
  dataSource.setDriverClassName(System.getProperty("driverClassName"));
  dataSource.setUser("username");
  dataSource.setPassword("password");
  dataSource.setServerName("localhost");
  dataSource.setPort(3306);
  dataSource.setDatabaseName("databasename");

وثم الربط:

Context context = new InitialContext();
context.bind("java:comp/env/jdbc/LegacyDataSource",datasource); 

وأو شيئا من هذا القبيل، والأمل أن يساعدك.

وحظا سعيدا!

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