Skip to content

Instances that are mocked cannot be asserted when they are used as parameters to mocked methods #1

@joeythomaschaske

Description

@joeythomaschaske

Given these classes

public class CarFactory {
    public Car getCustomizedCar() {
        Car car = Car.newInstance('Mercedes');
        CarCustomizer customizer = CarCustomizer.newInstance();
        customizer.customize(car);
        car.save();
        return car;
    }
}

public class Car {
    @TestVisible
    private static Car instance;

    private String type;

    public static Car newInstance(String type) {
        if (instance == null) {
            return new Car(type);
        }

        return instance;
    }

    public Car(String type) {
        this.type = type;
    }

    public void save() {
        
    }
}

public class CarCustomizer {
    @TestVisible
    private static CarCustomizer instance;

    public static CarCustomizer newInstance() {
        if (instance == null) {
            return new CarCustomizer();
        }

        return instance;
    }

    public Car customize(Car car) {
        // customize
        return car;
    }
}

And this test class

@IsTest
private class CarFactoryTest {
    @IsTest
    private static void customizesTheCar() {
        // given
        MockClass carMock = new MockClass();
        MockMethod saveMock = new MockMethod('save', new List<Object> { null });
        carMock.addMockMethod(saveMock);

        MockClass carCustomizerMock = new MockClass();
        MockMethod customizeMock = new MockMethod('customize', new List<Object> { null });
        carCustomizerMock.addMockMethod(customizeMock);

        Car.instance = (Car) Test.createStub(Car.class, carMock);
        CarCustomizer.instance = (CarCustomizer) Test.createStub(CarCustomizer.class, carCustomizerMock);

        // when
        CarFactory.getCustomizedCar();

        // then
        Assert.areEqual(1, customizeMock.getTimesCalled());

        Car expectedCar = new Car('Ford');
        Assert.areNotEqual(expectedCar, customizeMock.getNthCalledWith(1)[0]);
    }
}

This test won't work as expected because Car is being mocked with a constant type. We won't be able to assert that the correct type of car is being passed to customize, in this case Mercedes.

It would be useful to include a mechanism to allow real instances to be created instead of always returning the mock

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions