0

This is my first post in Stackoverflow, so far I have been the active reader of this forum and I am posting my first question here.

This is regarding the EasyMock usage, I am a new user of EasyMock and in the following example code I am setting expectation for a collaborator method with the same object to be returned (doesn't matter whether it is same object or different object but the result is same) and I am resetting before going out of the test method. but when the second test is executed, the mocked method is returning null, I am not sure why is this happening.

If I run the methods

@RunWith(PowerMockRunner.class)
@PrepareForTest({CollaboratorWithMethod.class, ClassTobeTested.class})
public class TestClassTobeTested {

private TestId testId = new TestId();

 @Test
public void testMethodtoBeTested() throws Exception{
    CollaboratorWithMethod mockCollaborator = EasyMock.createMock(CollaboratorWithMethod.class);
    PowerMock.expectNew(CollaboratorWithMethod.class).andReturn(mockCollaborator);
    EasyMock.expect(mockCollaborator.testMethod("test")).andReturn(testId);
    PowerMock.replay(CollaboratorWithMethod.class);
    EasyMock.replay(mockCollaborator);
    ClassTobeTested testObj = new ClassTobeTested();
    try {
        testObj.methodToBeTested(); 
    } finally {
        EasyMock.reset(mockCollaborator);
        PowerMock.reset(CollaboratorWithMethod.class);
    }
}  

@Test
public void testMothedtoBeTestWithException() throws Exception {
    CollaboratorWithMethod mockCollaborator = EasyMock.createMock(CollaboratorWithMethod.class);
    PowerMock.expectNew(CollaboratorWithMethod.class).andReturn(mockCollaborator);
    EasyMock.expect(mockCollaborator.testMethod("test")).andReturn(testId);
    PowerMock.replay(CollaboratorWithMethod.class);
    EasyMock.replay(mockCollaborator);
    ClassTobeTested testObj = new ClassTobeTested();
    try {
        testObj.methodToBeTested();
    } finally {
        EasyMock.reset(mockCollaborator);
        PowerMock.reset(CollaboratorWithMethod.class);
    }
}

}

Here is my Collaborator class

public class CollaboratorWithMethod {
   public TestId testMethod(String text) throws IllegalStateException {
     if (text != null) {
        return new TestId();
     } else {
        throw new IllegalStateException();
     }
  }
}

And here is my class under test

public class ClassTobeTested {

public static final CollaboratorWithMethod collaborator = new CollaboratorWithMethod();

public void methodToBeTested () throws IOException{
    try {
        TestId testid = collaborator.testMethod("test");
        System.out.println("Testid returned "+ testid);
    } catch (IllegalStateException e) {
        throw new IOException();
    }
}
}

I am looking for help from you guys to understand what exactly is happening here

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Muthu
  • 3
  • 1
  • 2
  • Not sure if it is because the collaborator is defined final in ClassTobeTested. – Bhushan Bhangale Apr 16 '13 at 05:06
  • could be, but not sure how can I resolve the issue in this case wihout modifying the ClassTobeTested as I don't want to touch my ClassTobeTested just because I could not unit test the same – Muthu Apr 16 '13 at 05:25
  • at least confirm the same. – Bhushan Bhangale Apr 16 '13 at 05:53
  • Yes, You are right. it is because of the same – Muthu Apr 16 '13 at 06:12
  • Now since you cannot modify the class and its a final variable, the reference once assigned cannot be changed. You should set the mock reference once using @BeforeClass and make "mockCollaborator" a global variable so that you can use the reference in multiple test cases. – Bhushan Bhangale Apr 16 '13 at 06:27
  • Yes, that worked. thanks for you hint. But what I still don't understand is that, why my second method above did not fail as I am expecting the constructor of CallaborarWithMethod to be called with the line PowerMock.expectNew(CollaboratorWithMethod.class).andReturn(mockCollaborator);, shouldn't powermock throw an exception saying that it is unexpected second as final can't modified instead of silently accepting and finally returning null. This makes it very difficult to root cause, isn't it? – Muthu Apr 16 '13 at 07:04
  • I don't think PowerMockito checks that the variable is final and is already assigned. – Bhushan Bhangale Apr 16 '13 at 07:28
  • I have added my comments as an answer so that you can accept/vote up. – Bhushan Bhangale Apr 16 '13 at 07:32

1 Answers1

0

The collaborator variable in class ClassTobeTested is final. The first test case initalizes the variable with mock object. The second test case cannot initialize the variable again. You set the expectation on the mock object created in second test case but actually the variable is still referring to the first mocked object.

Since you do not want to modify the class, you should set the mock reference once using @BeforeClass and make "mockCollaborator" a global variable so that you can use the reference in multiple test cases.

Bhushan Bhangale
  • 10,921
  • 5
  • 43
  • 71
  • Yes, Thanks for you explanation, that solves my problem. But I would expect PowerMock to report some error when we expect the consturction again in the second test method. I also tried using WhilteBox.setInternalState and that worked well even if I tried to set different objects for the final varibale in different test methods. Anyways, thanks much for you help. – Muthu Apr 16 '13 at 11:13