Sunday, January 11, 2015

How could I unit test inner class?

Given the source code below, how could I effectively unit test the Message class, the inner class of MainMsg? The challenge for this use case is Message class doesn't have any public interface that could access from outside world, the only entry is from MainMsg's addMessage(). How could I return a fake data when getMsgList() is called? Or I shouldn't mock Message class actually, just instantiate a new value is more than enough.
public class MySystem {
 public static void getMessage(MainMsg mm) {
  if( mm.getMsgList().size() > 0 ) {
   … 
   … 
  }
 }
}

public class MainMsg {
 private List<Message> msgList = new ArrayList<Message>();
 public class Message {
  private String str;
  Message(String str) {
   this.str = str;
  }
 }
 public void addMessage(String content) {
  msgList.add(new Message(content));
 }
 public List<Message> getMsgList() {
  return msgList;
 }
}
According to the advice from expert, I shouldn’t mock the inner class, whereas I should create a real value of it. But how? After a long R&D, I found EasyMock could handle this very well. In my unit test class, this is how I did it:
@RunWith(PowerMockRunner.class)
@PrepareForTest({MySystem.class})
public class MySystemTest {
 private MainMsg mm;
 @Test
 public void testSendMessage () throws IOException {
  mm = PowerMock.createPartialMock(MainMsg.class, "getMsgList");
  EasyMock.expect(mm.getMsgList()).andStubAnswer(new IAnswer<List<Message>>() {
   @Override
   public List<Message> answer() throws Throwable {
    Whitebox.setInternalState(mm, new ArrayList<Message>());
    mm.addMessage("message_A");
    List<Message> fakeMsgList = Whitebox.getInternalState(mm, "msgList");
    return fakeMsgList;
   }
  });

  MySystem.getMessage(mm);
 }
}

No comments: