1

I have an EJB which I want to unit test its public methods. I am testing EJB as a pojo. So I just have instantiate it and called the public method.

The problem is that public method sets some glassfish environment properties the environment variable is private. So I am not able to set it outside of the class and when I just call that public method for the environment object it throws nullPointerException.

The class that I want to test has,

@Resource(name="NameServiceEnvironment")
private Properties nameServiceEnvironment;



    public void setup() {

        // Set the environment.
        Properties environment = new Properties(); 
        environment.setProperty("name.host", this.nameServiceEnvironment.getProperty(NAME_HOST));
        environment.setProperty("name.port", this.nameServiceEnvironment.getProperty(NAME_PORT));

...}

So now for nameServiceEnvironment it throws the null pointer exception.

Now from the test class I've just instantiated the above class and called the setup method.

Thanks.

Don Roby
  • 40,677
  • 6
  • 91
  • 113
Sara
  • 2,417
  • 7
  • 35
  • 52

4 Answers4

2

You always have access, even to private methods. Use reflection in your test to gain access to the private properties - set them and get on with it.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • I thought it's only possible to access private constructor via reflection not the private methods. – Eng.Fouad Jul 14 '12 at 02:16
  • Wrong - you can access private everything with reflection - methods, ctors, data members, everything. – duffymo Jul 14 '12 at 02:40
  • 1
    http://stackoverflow.com/questions/11483647/how-to-access-private-methods-and-private-data-members-via-reflection – Eng.Fouad Jul 14 '12 at 12:56
  • Thanks. But when I use reflection, I set that private variable as type Field. The type is actually Properties. So I set that with type Field. E.g. Field nameServiceEnvironment = NameServiceEJB.class.getDeclaredField("nameServiceEnvironment"); And then I assign a local Properties type variable to it in test method. But then the class which I am testing uses nameServiceEnvironment.getProperty("",""); Although I assigned the environment variable with reflection at test method it still throws null exception. – Sara Jul 15 '12 at 00:38
  • There was another problem. Plz disregard my above comment. – Sara Jul 15 '12 at 01:42
2

Add a setter for nameServiceEnvironment and inject your own nameServiceEnvironment when unit testing.

Update based on comment

or, you could extract the properties bit from setup into another method and override it in your test to fake out.

public void setup() { 
    setupEnvironment();            
    ...
}

void setupEnvironment(){ //you would override this in your unit test
   Properties environment = new Properties(); 
   environment.setProperty("name.host", this.nameServiceEnvironment.getProperty(NAME_HOST));
   environment.setProperty("name.port", this.nameServiceEnvironment.getProperty(NAME_PORT));
}

Well, not exactly a fake. You simply bypass this bit in your test.

Liggy
  • 1,181
  • 2
  • 11
  • 19
  • That is what I was thinking. But my manager says for privacy reasons he doesn't want event the setter or getter methods for glassfish environment variables. – Sara Jul 14 '12 at 01:41
  • 1
    Well, not sure how only exposing the setter introduces privacy risk. In any case, I've updated my answer to include an alternative. – Liggy Jul 14 '12 at 01:50
1

Your nameServiceEnvironment is set using

@Resource(name="NameServiceEnvironment")

so you just need to make sure your test environment has that resource configured (as it does in your Glassfish environment). You could use Spring for example.

MattR
  • 6,908
  • 2
  • 21
  • 30
1

Is it because nameServiceEnvironment is not injected? This was one of the reasons Arquillian became popular. I used it for several months to unit test ejb's in a container, but it was not easy to use (for me at least). Using arquillian, you can have all the dependency injection done, and then the test methods executed. I've also used reflection as another suggested. And depending on what DI framework you use, you can probably configure it for a test to inject that as well.

reflection code if you want to do that:

public class ATest {

@Test
public void testEjb() throws Exception {
    MyEJB myEjb = new MyEJB();
    Class<? extends MyEJB> cls = myEjb.getClass();
    Field field = cls.getDeclaredField("props");
    field.setAccessible(true);
    field.set(myEjb, new Properties());
    myEjb.somePublicMethod();
}   
class MyEJB {
    private Properties props;
    public void somePublicMethod() {
        System.out.println("props has: " + props);
    }
}

}

Alper Akture
  • 2,445
  • 1
  • 30
  • 44
  • Yes I tested the above. Still I am getting same exception. Maybe because there we have set that private variable as Field but here at the class it is Properties type. I am not sure. – Sara Jul 15 '12 at 00:45