How to mock a private function in Junit

Asked

Viewed 658 times

-2

I have a main class Usuario extending (extends) an abstract class called Sessao, and uses a function of Sessao calling for obterDados() that takes session data and returns to an object SessaoTO. I need to mock this function so it returns the mocked object and follow the flow.

I’ve tried mocking the class Sessao as follows:

// Declaração feita na classe
@Mock
Sessao sessao;

...

// Declaração feita na função de teste
SessaoTO sessaoTO = new SessaoTO();
sessaoTO.setCpf("47566611100");
sessaoTO.setNome("Gaus");
sessaoTO.setSigla("user");

when(sessao.obterDados()).thenReturn(sessaoTO);

The problem is that at the time of execution is giving Nullpointer error because this mock is not working. I have tried using the @InjectMocks, but it didn’t work.

  • 1

    Hello! Share the code of the User and Session class if possible. I confess that, already in advance, User extend a class called Sessao does not seem to me a correct approach.

  • I didn’t implement the class code. I’m just doing the unit tests.

  • I don’t know if mockite allows private method mocking in newer versions, but you can do it using powermock: https://github.com/powermock/powermock/wiki/Mockito#how-to-Verify-private-behavior

  • Closely related but not duplicated: https://answall.com/q/269196/132

1 answer

1

You can’t mock a private method. The idea of the mock is for you to provide false implementations of objects and not isolated methods (even more so when private). Moreover, a private method is by definition an internal functionality of an object hidden from the outside world. It is something like that piece of code that to not be duplicated was isolated in a separate method. Therefore, there should be no reason to try to mock a private method.

The idea of mock testing is for you to provide the object being tested with mock implementations of the other objects with which it will interact.

However, in your case, it seems that this is not what you are trying to do, but rather mock only some of the object’s methods. This is not how it should be. Either the object contains the full implementation you want to exercise or it is a mock. There is no middle ground.

So your problem is that you want to inject the SessaoTO that should be produced. This suggests that you could use the design pattern Strategy or Factory. Instead of your object Sessao manufacture the SessaoTO in a private method, he would ask for the Strategy or the Factory injected into it to do it. That way, you could mock that Strategy or Factory to provide the SessaoTO that you want.

Other questions I find relevant to your case:

  • I am trying to mock a part of the process from which it is not possible to run in a Junit test because it needs all the rest of the process running (including the network part). This method from which I am trying to mock fails to fetch data correctly and ends up causing a Nullpointer error in the middle of the test.

  • @Isdeniel Again, you should mock objects, not isolated methods. That’s not how you’re trying to make things work, and trying to force the bar won’t work. Separate the contents of the private method into another class represented by an interface created for this and then you will be able to mock it easily. The idea here is to precisely separate the parts from each other properly to be able to use the mocks, and if you are not able to use them, it is a strong sign that things are not properly separated.

  • @Isdeniel I could even tell you how to rearrange things to achieve this separation, but the code that is in the question is insufficient for me to point it out.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.