Написание контрольного примера для DAO в приложении J2ee

Я пытаюсь написать несколько тестов для моих классов DAO в приложениях J2EE. Методы в моих классах DAO пытаются установить соединение с базой данных на основе URL JDBC (который находится на сервере приложений). Так что из внешнего интерфейса, если я нажму кучу вещей и сделаю триггер DAO, он будет работать нормально. Однако когда я пишу тестовые случаи для DAO, а объект DAO вызывает метод, он не может получить соединение с базой данных. Я думаю, поскольку ресурс JDBC находится на сервере приложений, поэтому он не работает с тестовым классом.

из-за этого, когда я запускаю свои тесты вместо pass или fail..it возвращает кучу ошибок.

Кто-нибудь сталкивался с этой проблемой? что я могу сделать, чтобы преодолеть это?

Пример:

public class DBConnectionManager {
   public static final String DB_URL = "jdbc/RSRC/my/connection/mydb"
   public Connection getconnection ()
   {
     DataSource ds = ServiceLocator.getInstance().getDataSource(DB_URL);
     return ds.getconnection();
   } 
}
public class MyDAO extends DBConnectionManager {
    publci SomeBean getContents (String id)
    {
        Connection con = getConnection();
        CallableStatement cs = con.prepareCall("{call myStorProc(?)}");
        cs.setString(1, id);
        ...
        //code to call resultset and retrieve SomeBean goes here
        ..
        return SomeBean;                
    }
}
public class MyTests extends TestCase {
    public testGetcontents ()
    {
        MyDAO myd = new MyDAO ();
        SomeBean smb = myd.getContents("someparm");
        assertEquals (5, smb.getSomeVal());
    }
}

Должен ли я делать что-то дополнительное в моем тестовом примере...? Если да, то?

РЕДАКТИРОВАТЬ:

Я получаю ошибку:

java.lang.NoClassDefFoundError: com/iplanet/ias/admin/common/ASException
        at java.lang.ClassLoader.defineClass1(Native Method)

4 ответа

Решение

В вашем DAO есть строка поиска JNDI, жестко связанная с ней. Если у вас нет службы поиска JNDI, она не сможет установить соединение.

Я не думаю, что DAO должен нести ответственность за установление соединения с базой данных. Этот дизайн не позволит вам устанавливать транзакции для единицы работы, потому что DAO не может знать, является ли она частью большей единицы работы.

Я бы рекомендовал передать соединение в DAO, возможно, в его конструктор. Таким образом, сервисный уровень может устанавливать соответствующие границы транзакций, если в одной единице работы имеется более одного DAO.

Эта конструкция будет иметь дополнительное преимущество, позволяя вашему приложению правильно использовать свой ресурс JNDI и ваш тест для получения соединения с DriverManager без необходимости поиска JNDI. У вас есть два разных источника для получения DataSource или Connection - один для приложения и другой для теста.

ОБНОВИТЬ:

Вот что я имею в виду, выраженный в вашем коде:

public class DBConnectionManager 
{
    public static final String DB_URL = "jdbc/RSRC/my/connection/mydb"

    public Connection getConnection (String jndiLookup)
    {
        DataSource ds = ServiceLocator.getInstance().getDataSource(jndiLookup);

        return ds.getconnection();
    } 

    public Connection getConnection(String driver, String url, String username, String password)
        throws ClassNotFoundException, SQLException
    {
        Class.forName(driver);

        return DriverManager.getConnection(url, username, password);
    }
}

public class MyDAO 
{
    private Connection connection;

    public MyDao(Connection connection)
    {
        this.connection = connection;
    }

    public SomeBean getContents (String id)
    {
        CallableStatement cs = this.connection.prepareCall("{call myStorProc(?)}");
        this.connection.setString(1, id);

        //code to call resultset and retrieve SomeBean goes here

        return someBean;                
    }
}

Вы ничего не показываете о закрытии ресурсов или транзакций. Судя по этому коду, у вас будут проблемы в обоих случаях. Я бы тщательно подумал о вашей реализации.

Я рекомендую Spring JDBC вам. Вы можете написать свои DAO s весной, не переписывая все ваше приложение.

Я также укажу, что вы также можете посмотреть на дженерики: не повторяйте DAO.

Сначала хорошо проверьте ваш ServiceLocator. Как вы упомянули, проблема, вероятно, заключается в том, что источник данных объявлен на сервере. Здесь "куча ошибок" должна быть полезной, как в том, что проблема заключается в получении DataSource или самого Connectiion. Какую базу данных вы используете? Можете ли вы войти в систему с вашего компьютера из консоли? Если нет - настройте его так, чтобы ваш хост был разрешен.

Там, где я работаю, наши DAO имеют инъекционное соединение (через инжекцию конструктора), и мы тестируем модуль на фиктивное соединение. Чтобы протестировать код в DAO, мы передаем имитированное (обычно с помощью Mockito) соединение и устанавливаем в наших модульных тестах ожидания относительно того, какие методы будут вызываться. Это делает тесты несколько шумными, так как тесты очень похожи на разрабатываемый код, но это работает для нас.

Это может быть проблема с правами доступа к базе данных, к которой вы пытаетесь получить доступ. Какие ошибки вы получаете?

Одним из полезных способов проверки доступа к базе данных является создание чистой локальной "тестовой" версии базы данных в качестве части вашего тестового набора. Прежде чем запускать свои тесты, используйте сценарии для создания локальной копии базы данных со всеми соответствующими данными, а затем запустите свои тесты на этом, а не на удаленном сервере.

Люди могут утверждать, что тестирование на базе данных в модульном тесте на самом деле не является модульным тестом, поскольку имеет внешнюю зависимость. Если вы можете реорганизовать ваши классы DAO, вы можете сделать так, чтобы фактический источник данных был внедрен через некоторые интерфейсы. В вашем тестовом коде вы вставляете "фиктивный" источник данных, который предоставляет ваши тестовые данные в каком-то виде в формате памяти, а затем на производстве вы используете / внедряете фактические исходные классы базы данных. Если вы можете скрыть внешние (не связанные с бизнес-кодом) части вашего DAO за интерфейсами, вы можете использовать mocks в своих модульных тестах для проверки большей части вашей функциональности, а не фактического доступа к данным.

Другие вопросы по тегам