I'm trying to mock only a method (getValue
) of a class (Collaborator
) that extends another (Person
). However, after setting the Expectations
block, constructors of the mocked class are not executing super(...)
when this method is called.
The following example is an adaptation from the code shown here: http://jmockit.org/tutorial/Mocking.html#partial
The problem happens with the object Collaborator c3
. The last assert
fails, and I expected it to pass.
public class PartialMockingTest
{
static class Person
{
final int id;
Person() { this.id = -1; }
Person(int id) { this.id = id; }
int getId() { return id; }
}
static class Collaborator extends Person
{
final int value;
Collaborator() { value = -1; }
Collaborator(int value) { this.value = value; }
Collaborator(int value, int id) { super(id); this.value = value; }
int getValue() { return value; }
final boolean simpleOperation(int a, String b, Date c) { return true; }
}
@Test
public void partiallyMockingAClassAndItsInstances()
{
final Collaborator anyInstance = new Collaborator();
new Expectations(Collaborator.class) {{
anyInstance.getValue(); result = 123;
}};
// Not mocked, as no constructor expectations were recorded:
Collaborator c1 = new Collaborator();
Collaborator c2 = new Collaborator(150);
Collaborator c3 = new Collaborator(150, 20);
// Mocked, as a matching method expectation was recorded:
assertEquals(123, c1.getValue());
assertEquals(123, c2.getValue());
assertEquals(123, c3.getValue());
// Not mocked:
assertTrue(c1.simpleOperation(1, "b", null));
assertEquals(45, new Collaborator(45).value);
assertEquals(20, c3.getId()); // java.lang.AssertionError: expected:<20> but was:<-1>
}
}
Am I doing something wrong? Is it a bug?
I'm not really well versed into the internals of the Expectations system, but after debugging the code I realized that the declaration of the expectation prior to the construction of the objects was messing with the constructors' invocation.
In that way, if you move the Expectation after the constructions the test should pass
final Collaborator anyInstance = new Collaborator();
// Not mocked, as no constructor expectations were recorded:
Collaborator c1 = new Collaborator();
Collaborator c2 = new Collaborator(150);
Collaborator c3 = new Collaborator(150, 20);
new Expectations(Collaborator.class) {{
anyInstance.getValue(); result = 123;
}};
// Mocked, as a matching method expectation was recorded:
assertEquals(123, c1.getValue());
assertEquals(123, c2.getValue());
assertEquals(123, c3.getValue());
// Not mocked:
assertTrue(c1.simpleOperation(1, "b", null));
assertEquals(45, new Collaborator(45).value);
assertEquals(20, c3.getId()); //it works now