writing test case for a DAO on a J2ee Application

随声附和 提交于 2020-01-02 10:08:35

问题


I am trying to write some test cases for my DAO classes in a J2EE applications. Methods in my DAO classes try to get connection to the Database based on a JDBC URL (which is on the app server). So from the front end if I click bunch of stuff and make the DAO trigger it runs fine. However, when I write tests cases for the DAO and the DAO object calls the method then it is not able to get the connection to the database. I think since the JDBC resource is on the App server that is why it is not working from the test class.

because of this when I run my tests instead of pass or fail..it returns bunch of errors.

Has someone encountered this issue? what can I do to overcome this?

Example:

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());
    }
}

Should I be doing something extra in my testcase...? if so what?

EDIT:

error I get is:

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

回答1:


Your DAO has a JNDI lookup string hard wired into it. Unless you have a JNDI lookup service available, it won't be able to get a connection.

I don't think a DAO should be responsible for acquiring a database connection. This design won't allow you to set transactions for a unit of work, because a DAO can't know if it's part of a larger unit of work.

I'd recommend passing the connection into the DAO, perhaps into its constructor. That way a service layer can establish appropriate transaction boundaries if there's more than one DAO in a single unit of work.

This design will have the added benefit of making it possible for your application to use its JNDI resource appropriately and your test to get its connection from a DriverManager, without having to use a JNDI lookup. You have two different sources for acquiring the DataSource or Connection - one for the app and another for the test.

UPDATE:

Here's what I mean, expressed in your code:

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;                
    }
}

You show nothing about closing resources properly or transactions. Judging by this code, you'll be in trouble on both counts. I'd think carefully about your implementation.

I'll recommend Spring JDBC to you. You can write your DAOs in Spring without rewriting your whole app.

I'll also point out that you might also be looking at generics: Don't Repeat The DAO.




回答2:


Test well your ServiceLocator first. As you mentioned, the problem is probably because the datasource is declared on the server. Here the "bunch of errors" should be helpful, as of whether the problem is in acquiring the DataSource, or the Connectiion itself. What database are you using? Can you logon to it from your machine from console? If not - configure it so that your host is allowed.




回答3:


It could be a permissions issue on the database you're trying to access. What errors are you getting?

One useful way for testing database access is to create a clean, local "test" version of your database as part of your test harness. Before you run your tests, use scripts to create a local copy of the database with all the pertinent data, then run your tests against that, rather than the remote server.

People may argue that testing against a database in a unit test is not truly a unit test, since it has an external dependency. If you're able to refactor your DAO classes, you can make it so the actual data source is injectable through some interfaces. In your test code, you'd inject a "mock" data source which provides your test data in some in memory format, then in production, you'd use/inject the actual database source classes. If you can hide the external (non-business code related) parts of your DAO behind interfaces, you can use mocks in your unit tests to test more of your functionality, rather than the actual data access.




回答4:


Where I work our DAOs have an injectable connection (via constructor injection), and we unit test against a mock connection. To test the code in the DAO, we pass in a mocked (usually using Mockito) connection, and set up expectations in our unit tests as to what methods will be called. This makes for somewhat noisy tests, as the tests look very similar to the code being developed, but it works for us.



来源:https://stackoverflow.com/questions/1698212/writing-test-case-for-a-dao-on-a-j2ee-application

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!