I am writing unit test for the below code using junit and mockito
public class Abc implements Runnable
{
private static ServerSocket server;
private static int port;
public Abc(int cPort)
{
port = cPort;
}
public void run()
{
init();
}
public static void init()
{
try {
server = new ServerSocket(port);
...something...
client.close();
}
}
catch(IOException e)
{
System.out.println("Exception inside init()...");
e.printStackTrace();
}
}
};
Unit test I have written
@RunWith(PowerMockRunner.class)
@PrepareForTest({ServerSocket.class})
public class abcTest {
@Mock (name = "server") //same name as private var.
ServerSocket mockServer;
@InjectMocks
Abc abc;
@Test
public void testInit() throws Exception {
int port = 1880;
Socket mockClient = Mockito.mock(Socket.class);
PowerMockito.whenNew(ServerSocket.class).
withArguments(anyInt()).thenReturn(mockServer);
abc = new Abc(port);
Abc.init();
PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
}
};
But the call always go to original function definition. I am using junit 4.11 with mockito 2.28.2 and powermockito 2.0.2. I'm using java after a long time. Now its feel like kind of new. Please correct me if anything wrong in the code also.
You will need to change your PrepareForTest
annotation
to @PrepareForTest({Abc.class})
.
From the PowerMockito docu
:
This annotation tells PowerMock to prepare certain classes for testing. Classes needed to be defined using this annotation are typically those that needs to be byte-code manipulated
In this case that refers to the class which creates the new instance of ServerSocket
.
ServerSocket
itself is a non-final
public
class that does not require special handling from PowerMockito
(instead Mockito
can deal with this class on its own).
You could also change your test to do the following:
@Test
public void testInit() throws Exception {
int port = 1880;
ServerSocket mockServer = Mockito.mock(ServerSocket.class);
PowerMockito.whenNew(ServerSocket.class)
.withArguments(Mockito.anyInt()).thenReturn(mockServer);
Abc.port = port;
Abc.init();
PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
}
ABC
object, just could just set the static port variable directly.ABC
class into an object.
@InjectMocks
failed for me as there is no default constructor
(Actually I got an error message in the console when trying to execute your code)
Additonaly you create a new instance of ABC in your test, which would have overwritten the things done by the annotations. Also as server
is created during the init
call, there is no need to inject a mock for it.
powermockito 2.0.2
actually depends on junit 4.12
, so I am not sure what effects downgrading to an older version might have.
Socket mockClient
seemed somewhat unrelated to the code your posted, so I removed it from my example in the answer, however as you use a client
(I assume that is your Socket
) in your code your probably need to do some mocking for that as well and provide the mock to the method accordingly.