FixMaker
FixMaker

Reputation: 3877

JMockit: Mock both parent and child classes

This is a slightly simplified version of the result that I'm trying to achieve but I think it illustrates the problem.

Imagine I have the following two classes, where one is a descendant of the other:

public class Vehicle {

    protected String name;

    {
        name = "Vehicle";
    }

    public String getName() {
        return name;
    }

}

public class Car extends Vehicle {

    {
        name = "Car";
    }

}

I also have this test code:

public class VehiclesTest {

    @Test
    public void checkVehicles(@Mocked final Vehicle vehicleMock,
                              @Mocked final Car carMock) {
        new Expectations() {
            {
                vehicleMock.getName(); result = "mocked vehicle";

                carMock.getName(); result = "mocked car";
            }
        };

        Vehicle aVehicle = new Vehicle();
        System.out.println("Starting a " + aVehicle.getName());

        Vehicle aCar = new Car();
        System.out.println("Starting a " + aCar.getName());
    }
}

What I want to see on the console output is this:

Starting a mocked vehicle
Starting a mocked car

However, the actual output looks like this:

Starting a mocked car
Starting a mocked car

I'm new to JMockit so I think I know why this is happening (something due to the fact that JMockit will mock all ancestor classes of a mock all the way up the class hierarchy, excluding java.lang.Object).

How can I set up my expectations so that I get the result that I want? Is it possible to set expectations on multiple mocks of different classes in the same hierarchy (i.e. where one is a descendant of the other)?

Upvotes: 0

Views: 755

Answers (1)

Rogério
Rogério

Reputation: 16380

The following test will work:

@Test
public void checkVehicles(@Mocked Vehicle anyCarOrVehicle) {
    new Expectations() {{
        new Vehicle().getName(); result = "mocked vehicle";
        new Car().getName(); result = "mocked car";
    }};

    assertEquals("mocked vehicle", new Vehicle().getName());
    assertEquals("mocked car", new Car().getName());
}

Granted, the API in a case like this is not obvious. The best thing, as always, is to avoid mocking altogether, if you can. In particular, mocking is meant to be used for emulating and verifying behavior, not state. So, if you are mocking "getters", that's a strong sign of a bad testing approach.

Upvotes: 1

Related Questions