NPE in datasource

时间:2016-04-04 17:12:20

标签: java junit junit4

I'm trying to run this JUnit test but I get NPE:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class KnowledgebaseTest
{

    public KnowledgebaseTest()
    {
    }

    @BeforeClass
    public static void setUpClass() throws Exception
    {
        try
        {
            // Create initial context
            System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                "org.apache.naming.java.javaURLContextFactory");
            System.setProperty(Context.URL_PKG_PREFIXES,
                "org.apache.naming");
            InitialContext ic = new InitialContext();

            ic.createSubcontext("java:");
            ic.createSubcontext("java:/comp");
            ic.createSubcontext("java:/comp/env");
            ic.createSubcontext("java:/comp/env/jdbc");

            String host = "localhost";
            int port = 5432;
            String dbName = "crm";
            String username = "postgres";
            String password = "qwerty";

            Class.forName("org.postgresql.Driver");
            Connection conn = null;
            conn = DriverManager.getConnection("jdbc:postgresql://" + host + ":" + port + "/" + dbName, username, password);
            conn.close();

            ic.bind("java:/comp/env/jdbc/nameofmyjdbcresource", conn);

        }
        catch (NamingException ex)
        {
            Logger.getLogger(KnowledgebaseTest.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    @AfterClass
    public static void tearDownClass()
    {
    }

    @Before
    public void setUp()
    {
    }

    @After
    public void tearDown()
    {
    }

    @Resource(name = "java:/comp/env/jdbc/nameofmyjdbcresource")
    DataSource ds;

    @Test
    public void testPageFirst() throws SQLException
    {
        if (ds == null)
        {
            throw new SQLException("Can't get data source");
        }
        Connection conn = ds.getConnection();

        if (conn == null)
        {
            throw new SQLException("Can't get database connection");
        }

        PreparedStatement ps = null;
        boolean committed = false;
        try
        {
            conn.setAutoCommit(false);
            ps = conn.prepareStatement("UPDATE ACCOUNT SET LAST_LOGIN = CURRENT_DATE WHERE USER_NAME = ?");

            ps.setString(1, "TIMESTAMP");
            ps.executeUpdate();
            ps.close();

            conn.commit();
            committed = true;
        }
        finally
        {
            if (!committed)
            {
                conn.rollback();
            }

            if (ps != null)
            {
                ps.close();
            }
            conn.close();
        }
    }
}

For some reason ds is null. What is the proper way to initialize Data source object in JUnit test file?

java.sql.SQLException: Can't get data source

Can you propose some solution to fix this issue or better solution?

1 个答案:

答案 0 :(得分:2)

您的代码似乎不正确您应该绑定数据源而不是连接。要修复代码(假设您使用PGSQL),您需要绑定数据源,如下所示:

        import org.postgresql.jdbc2.optional.SimpleDataSource;
        ...
        SimpleDataSource dataSource = new SimpleDataSource();
        dataSource.setDatabaseName(dbName);
        dataSource.setPortNumber(port);
        dataSource.setUser(username);
        dataSource.setPassword(password);


        ic.bind("java:/comp/env/jdbc/nameofmyjdbcresource", dataSource);

然后您可以将setUp方法中的变量设置为下一个:

DataSource ds;

@Before
public void setUp() throws NamingException {
    this.ds = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/nameofmyjdbcresource");
}

无论如何,JUnit中没有默认魔法可以允许你注入数据源,因此如果你想与你最喜欢的JEE服务器进行真正的集成测试,那么JUnit默认会忽略@Resource(name = "java:/comp/env/jdbc/nameofmyjdbcresource") /资源注入,您可以查看arquillian