0

Here is my simple interface and an enum that implements it. I have written a very simple JUnit Test case, which fails because of NullPointerException. I do not understand why this Exception is thrown. I have constructed an enum object in the test class.

public interface Account {
    public String getName();
    public boolean isBillable();
}

public enum NonBillableAccount implements Account {

    SICK_LEAVE("SickLeave"),
    VACATION("Vacation"),
    BUSINESS_DEVELOPMENT("businessDevelopment");
    private String leaveType;

    private NonBillableAccount(String leavetype) {
        this.leaveType = leavetype;
    }

    @Override
    public String getName() {
        return this.leaveType;
    }

    @Override
    public boolean isBillable() {
        return false;
    }

}

And the JUnit test case here

public class NonBillableAccountTest {

    Account ac = null;
    @Before
    public void setUp() throws Exception {
        Account ac = NonBillableAccount.BUSINESS_DEVELOPMENT;
    }

    @Test
    public void testGetName() {
        assertEquals(ac.getName(),"businessDevelopment");
    }

    @Test
    public void testIsBillable() {
        assertEquals(ac.isBillable(), false);
    }

}
eagertoLearn
  • 9,772
  • 23
  • 80
  • 122
  • 7
    You're shadowing your `ac` variable in your `setUp()` method. Remove `Account` in `Account ac = NonBillableAccount.BUSINESS_DEVELOPMENT;`. – Alexis C. Jan 29 '14 at 21:41
  • Damn,I am doing this stupid for second time. why!!!!!! – eagertoLearn Jan 29 '14 at 21:46
  • 1
    No need to beat yourself up or get discouraged. Everyone starts somewhere. I still do amazingly stupid things in Python all the time, because I'm still learning the language. As long as you're always @eagertoLearn, you're good to go. :) – asteri Jan 29 '14 at 21:49
  • I do stupid stuff in languages I've known for years because that's just how it goes - typos, whitespace, colons instead of semicolons... Sometimes the simplest mistakes are the hardest to see. – doublesharp Jan 29 '14 at 21:59

2 Answers2

3

You are not setting the ac field of the overarching class. You are hiding it (actually known as shadowing) with a new Account ac variable. To fix this, simply remove the Account type name before the variable assignment.

You can also refer to the variable with this.ac, but there's no need so long as you don't declare a variable with the same name in the local scope before you reference it.

asteri
  • 11,402
  • 13
  • 60
  • 84
3

By referring to ac with the Account type modifier as follows you are causing it to be treated as a local variable:

// Create a local variable "ac", does not affect the class variable
Account ac = NonBillableAccount.BUSINESS_DEVELOPMENT;
if (this.ac == null){
   System.println('It does still equal null!'); // yep, it's null
}

Try this instead to set the ac property on your test class:

// refers to the class variable implicitly
ac = NonBillableAccount.BUSINESS_DEVELOPMENT; 

or

// refers to the class variable explicitly
this.ac = NonBillableAccount.BUSINESS_DEVELOPMENT; 

This is known as "shadowing" (explained here) which allows you to use the same variable names in different contexts. In your test methods it expands ac to this.ac in the compiler, which throws the NPE when you call ac.getName() as you have not set the class property yet.

Community
  • 1
  • 1
doublesharp
  • 26,888
  • 6
  • 52
  • 73
  • No need for an explicit `this`. That may confuse the OP about the concept of shadowing. He could in fact use `this.ac` after declaring a new `Account ac` in the local scope to accomplish what he wanted. He ought to be clear about how the actual hiding mechanism works to avoid this in the future. – asteri Jan 29 '14 at 21:45
  • 1
    True, I was trying to highlight the incorrect scope in the example by using `this` in mine but I see what you mean. – doublesharp Jan 29 '14 at 21:47
  • :) Just want him to get what's going on instead of just making the code work this once. +1 – asteri Jan 29 '14 at 21:48