1

I tried to testing my Dao class but it return this error for the class DbConnection:

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or in an application resource file: java.naming.factory.initial at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:691) at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305) at java.naming/javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:342) at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409) at model.DbConnection.(DbConnection.java:16) at model.DbConnection.getInstance(DbConnection.java:30) at model.ProfileManager.ReturnPatientByKey(ProfileManager.java:27) at model.ProfileManagerTest.testReturnPatientByKey(ProfileManagerTest.java:32) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) ....

my DbConnection class:

package model;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class DbConnection {

    private DbConnection() {

        Context ctx;
        try {
            ctx = new InitialContext();
            ds = (DataSource)ctx.lookup("java:comp/env/jdbc/CheckUpDb");
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    public Connection getConnection() throws SQLException {
        return ds.getConnection();

    }

    public static DbConnection getInstance () {
        if(db==null) {
            return new DbConnection();
        }
        else {
            return db;
        }
    } 

    private static DataSource ds;
    private static DbConnection db;
}

Database connection works in the web application, only the testing return this error. I don't think the problem si my class ProfileManager because it is only a testing example:


import static org.junit.Assert.assertTrue;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import model.Bean.PatientBean;

class ProfileManagerTest{

    private ProfileManager pm;
    String fiscal_code;
    String user_password;
    PatientBean patient;
    
    @BeforeEach
    void setUp() throws Exception {
        this.pm = new ProfileManager();
        fiscal_code = "aaa";
        user_password = "bbb";
        patient = mock(PatientBean.class);
    }

    @AfterEach
    void tearDown() throws Exception {
    }

    @Test
    void testReturnPatientByKey() {
        patient = (PatientBean) pm.ReturnPatientByKey(fiscal_code, user_password);
        assertTrue(true);
    }

}
Martha
  • 35
  • 1
  • 8

1 Answers1

1

Database connection works in the web application, only the testing return this error.

That's most likely because you have the datasource declared in the server configuration and the server is providing your web app with one, but you don't have the same done in your test.

Do a search in your server files an you will probably discover something like this, or similar, depending on what server you use:

<Resource name="jdbc/CheckUpDb" 
  driverClassName="..." 
  type="..." 
  url="..." 
  username="..." 
  password="..." 
/>

This is a way to configure a datasource using JNDI. When your web application runs, the server will provide you with this resource by name. This is what ctx.lookup("java:comp/env/jdbc/CheckUpDb"); does. It asks the server to give it that resource.

But when you run your unit tests, you run outside the server environment. That means that any resource you defined in the server (using context.xml for example) doesn't exist when you run your tests. In your tests you have to provide a datasource and make it available to your JNDI context so that this line of code then works:

ds = (DataSource)ctx.lookup("java:comp/env/jdbc/CheckUpDb");

The following post should give you the necessary details to set up your JNDI data source for your test: Setting up JNDI Datasource in jUnit

You will see that the examples there make use of a library called Simple-Jndi that they use to provide a JNDI context and configure it to include the datasource that the tests then try to retrieve by name. You can use any JNDI provider, but you must set up the datasource for your test yourself (inside @BeforeEach or @BeforeAll) because when running unit tests, you don't have the tomcat server doing this for you.

Bogdan
  • 23,890
  • 3
  • 69
  • 61
  • Iuse tomcat with eclipse in a maven project. Where should I enter what you wrote? I tried to insert this code into Tomcat's context.xml file but it gives me the same error: `` – Martha Feb 03 '21 at 14:51
  • You said *Database connection works in the web application, only the testing return this error*. Are you running the unit test from tomcat? That doesn't seem right. And if the web application works then you must have the `CheckUpDb` already declared somewhere. Have you searched for it? In the Unit tests you will setup the context in `@BeforeEach` or `@BeforeAll`, depending you how you want to run your tests. – Bogdan Feb 04 '21 at 09:05
  • https://stackoverflow.com/questions/66036577/cannot-invoke-javax-sql-datasource-getconnection-because-model-dbconnection-ds @Bogdan Here all my code. Test and class under test are in the same project. Yes, the database connection works fine, but unit test is the problem. I'm using junit-jupiter version 5.6.0. How you can see in the link, CheckUpDb is already declared in context.xml . – Martha Feb 04 '21 at 09:32