Fernando Ania
Fernando Ania

Reputation: 377

JUnit calling a method which calls another method returns nullPointerException

I want to test the method randomPlayerStart which calls a setter method from the Player class. I created a testcase which checks the value of the boolean value of the player.

@Before
public void setUp() throws Exception {
    playerA = new Player("Player A", false);
    playerB = new Player("Player B", false);
    activity = new MainActivity();
    activity.randomPlayerStart();
}

@Test
public void testrandomPlayerStart() throws Exception {
    assertEquals(true,playerB.isTurn());
}

This is the randomPlayerStart method.

public void randomPlayerStart() {
    Random random = new Random();
    boolean player = random.nextBoolean();

    if (player) {
        playerA.setTurn(true);
    } else {
        playerB.setTurn(true);
    }
}

I have tried overriding the methods within the test file and attempted to use Spy from the mockito framework, but it didn't work. I don't get a nullException error when I used doNothing instead of doAnswer but then the method does not called.

@Before
public void setUp() throws Exception {
    Turn = false;
    playerA = new Player("Player A", false) {
        public void setTurn(boolean turn) {
            Turn = turn;
        }
    };
    playerB = new Player("Player B", false) {
        public void setTurn(boolean turn) {
            Turn = turn;
        }
    };
    activity = new MainActivity() {
        public void randomPlayerStart() {
            Random random = new Random();
            boolean player = random.nextBoolean();

            if (player) {
                playerA.setTurn(true);
            } else {
                playerB.setTurn(true);
            }
        }
    };
    MainActivity spy = Mockito.spy(activity);

    doAnswer(new Answer() {
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            activity.randomPlayerStart();
            return null;
        }
    }).when(spy).randomPlayerStart();
    spy.randomPlayerStart();
}

I am not sure what to try next, I have no experience with testing so any comments or directions are very much appreciated.

Upvotes: 2

Views: 2594

Answers (2)

Fernando Ania
Fernando Ania

Reputation: 377

Following the comment njzk2. I decided to created another class (MainActivity presenter) which takes three values, an interface and two player objects.

public class MainActivityPresenter {
MainActivityView view;
Player playerA, playerB;


public MainActivityPresenter(MainActivityView view, Player playerA, Player playerB) {


    this.view = view;
    this.playerA = playerA;
    this.playerB = playerB;

}

public void randomPlayerStart() {
    Random random = new Random();
    boolean player = random.nextBoolean();

    if (player) {
        playerA.setTurn(true);
    } else {
        playerB.setTurn(true);


    }
}

public void initPlayers() {
    playerA = new Player("Player A", false);
    playerB = new Player("Player B", false);
    }
}

Then I created an interface which I implemented to the MainActivity class. Now it became possible to instantiate the MainActivityPresenter class.

public void startGame(){
    initPlayers();
    linkIds();
    initBtns();
    initCells();
    initLinkedList();
    randomPlayerStart();
    hand = new Hand(0);

    switchTurn();
    presenter = new MainActivityPresenter(MainActivity.this, playerA, playerB );



}
public void randomPlayerStart() {
    presenter.randomPlayerStart();
}

Which means I can call the method randomPlayerStart() from the test class by instantiating the MainActivityPresenter class instead of the MainActivity class and not get NullException error.

Thank you All

Upvotes: 0

Kotse
Kotse

Reputation: 418

How about you move the Random outside of randomPlayerStart, you can then just mock that and easily test your method.

//omitted declarations

Random random;

@Before
public void setUp() throws Exception {
    playerA = new Player("Player A", false);
    playerB = new Player("Player B", false);
    activity = new MainActivity();

    random = mock(Random.class); //static import of Mockito.mock
}

@Test
public void testRandomPlayerStart_playerA() throws Exception {
    when(random.nextBoolean()).thenReturn(Boolean.TRUE); //static import of Mockito.when

    activity.randomPlayerStart(random);
    assertEquals(true,playerA.isTurn());
}

@Test
public void testRandomPlayerStart_playerB() throws Exception {
    when(random.nextBoolean()).thenReturn(Boolean.FALSE);

    activity.randomPlayerStart(random);
    assertEquals(true,playerB.isTurn());
}

your randomPlayerStart will need to accept random parameter public void randomPlayerStart(Random random)

Once dependency is moved outside testing is much easier, isn't it? :)

Upvotes: 1

Related Questions