Question

I'm attempting to write a unit test of a class that takes a DatagramPacket into its constructor. I've included both the test (first) and the class under test (second) below.

The issue is that none of the output I get is as I expect based on my when().thenReturn calls. In my test I have three print statements (look at the bottom of the test() method in the first code block). The output from it is

IP: 0.0.0.0, Port: 0, Data:

The output I intended is:

IP: 90.35.52.52, Port: 25200, Data: heartbeat^0a522

Does anyone happen to know why I'm not receiving the expected output?

Thank you!

UDPPacket_TEST.java

import static org.mockito.Mockito.*;

import java.net.DatagramPacket;
import java.net.InetAddress;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(DatagramPacket.class)
public class UDPPacket_TEST {

    DatagramPacket mDatagramPacket;
    UDPPacket mPacket;

    @Before
    public void setup() {
        PowerMockito.mockStatic(DatagramPacket.class);
        mDatagramPacket = PowerMockito.mock(DatagramPacket.class);
        InetAddress addRet = mock(InetAddress.class);
        when(addRet.getHostAddress()).thenReturn("90.35.52.52");
        PowerMockito.when(mDatagramPacket.getPort()).thenReturn(25200);
    }

    @Test
    public void test() {
        byte[] packetData = "heartbeat^0a552".getBytes();
        PowerMockito.when(mDatagramPacket.getData()).thenReturn(packetData);

        mPacket = new UDPPacket(mDatagramPacket);

        System.out.println(String.format("IP: %s, Port: %d, Data: %s", mPacket.getIP(), mPacket.getPort(), mPacket.getData()));
    }

}

UDPPacket.java

public class UDPPacket {

    String mIP;
    int mPort;
    String mData;

    public UDPPacket(DatagramPacket receivedPacket) {
        //Grab the information out
        mData = new String(receivedPacket.getData());
        mIP = receivedPacket.getAddress().getHostAddress();
        mPort = receivedPacket.getPort();
    }

    public String getIP() {
        return mIP;
    }

    public int getPort() {
        return mPort;
    }

    public String getData() {
        return mData;
    }

}
Was it helpful?

Solution

Not that I like the approach for testing (but I understand the necessity sometimes...). Dig into the source code for PowerMockito and you'll see that you're not creating a "mock" instance of DatagramPacket at all, your receiving a "regular" instance.

You can however set the fields of your instance using Whitebox:

        Whitebox.setInternalState(mDatagramPacket, "buf", packetData);

"Fixed" code...

UDPPacket_TEST.java

@RunWith(PowerMockRunner.class)
@PrepareForTest(DatagramPacket.class)
public class UDPPacket_TEST {

    DatagramPacket mDatagramPacket;
    UDPPacket mPacket;
    InetAddress addRet;

    @Before
    public void setup() {
        mDatagramPacket = PowerMockito.mock(DatagramPacket.class);
        addRet = mock(InetAddress.class);
        when(addRet.getHostAddress()).thenReturn("90.35.52.52");
        PowerMockito.when(mDatagramPacket.getPort()).thenReturn(25200);
    }

    @Test
    public void test() {
        byte[] packetData = "heartbeat^0a552".getBytes();
        Whitebox.setInternalState(mDatagramPacket, "buf", packetData);
        Whitebox.setInternalState(mDatagramPacket, "address", addRet);
        Whitebox.setInternalState(mDatagramPacket, "port", 25200);
        PowerMockito.when(mDatagramPacket.getData()).thenReturn(packetData);

        mPacket = new UDPPacket(mDatagramPacket);

        System.out.println(String.format("IP: %s, Port: %d, Data: %s", mPacket.getIP(), mPacket.getPort(), mPacket.getData()));
    }

}

Produce the output you want:

IP: 90.35.52.52, Port: 25200, Data: heartbeat^0a552
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top