Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent super class from being mocked by jmockit?

Tags:

java

jmockit

Given a class hierarchy that looks like this:

public class Vehicle {

    private String name;

    public Vehicle(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

}


public class Car extends Vehicle {

    public Car(String name) {
        super(name);
    }

    public String drive() {
        return "driving the car";
    }

    public String boardBus() {
        Bus bus = new Bus("bus to cut off");

        return bus.board();
    }

}

public class Bus extends Vehicle {

    public Bus(String name) {
        super(name);
    }

    public String board() {
        return "boarding the bus";
    }

}

I'm trying to test the Car class. However, Car also happens to make use of Bus. So, in my test, I'm trying to mock Bus. My test code looks like this:

import static org.junit.Assert.assertEquals;
import mockit.Mocked;
import mockit.NonStrictExpectations;

import org.junit.Test;

public class CarTest {

    @Test
    public void testCar() {
        final String name = "I am a car";
        final Car car = new Car(name);

        new NonStrictExpectations() {
            @Mocked Bus bus;

            {
                bus.board(); result = "test bus boarding";
            }
        };

        assertEquals("I am a car", car.getName());
    }

}

The assert fails because car.getName() returns null.

By inserting System.out.println's in the constructors for Vehicle, Car, and Bus, I'm suspecting that the "real" Vehicle that is loaded by new Car(name) is later replaced by a mocked Vehicle when the @Mocked Bus bus is executed.

Is there a way for jmockit to preserve the real Vehicle that is "instantiated" when Car is constructed?

like image 645
rdguam Avatar asked Nov 14 '22 19:11

rdguam


1 Answers

I see two solutions:

@Test
public void boardBus_usingInstanceSpecificMockingForNewedInstances()
{
    new Expectations() {
        @Capturing @Injectable Bus bus;

        {
            bus.board(); result = "mocked";
        }
    };

    String result = new Car("myCar").boardBus();
    assertEquals("mocked", result);
}

@Test
public void boardBus_usingPartialMocking()
{
    final Bus bus = new Bus("");
    new Expectations(bus) {{ bus.board(); result = "mocked"; }};

    String result = new Car("myCar").boardBus();
    assertEquals("mocked", result);
}
like image 56
Rogério Avatar answered Dec 17 '22 16:12

Rogério