Mockito: фиктивный объект, который не является членом, но создается встроенным - PullRequest
3 голосов
/ 26 мая 2020

У меня есть класс, который выполняет следующие действия:

public class Transformer {

    public void transform(final Car car) throws IOException {
        switch (car.getType()) {
            case OFFROAD:
                OffroadCar offroadCar = new OffroadTransformer().transform(car);

                // do something with offorad car

                break;
            ...
        }
    }
}

У меня есть тестовый класс:

public class TransformerTest {

    @InjectMocks
    private Transformer transformer;

    @Mock
    private OffroadTransformer offroadTransformer;

    @BeforeEach
    public void setup()
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testTransform() throws IOException {
        final Car car = new Car(OFFROAD);

        when(offroadTransformer.transform(any(Car.class))).thenReturn(new OffroadCar());

        transformer.transform(car);

        // make some verifictations
    }
}

Моя проблема теперь в том, что when не работает. Вместо имитации вызывается настоящий offroadTransformer.transform. Итак, я предполагаю, что макет не работает, потому что OffroadTransformer не является членом класса Transformer, а экземпляр создается встроенным.

Это правильно?

Если да: Как я могу поиздеваться над этим? Если нет: в чем еще может быть причина?

1 Ответ

3 голосов
/ 26 мая 2020

Проблема в том, что используемый объект OffroadTransformer не имитируется. Ваша тестовая установка создает макет в поле transformer, но этот макет не тот, который используется методом, и это подтверждает вашу гипотезу.

Используемая вами настройка работает с классами, которые имеют имитируемые объекты как поля экземпляра, например:

public class Transformer {

    //injected, initialized inline, etc.
    private OffroadTransformer transformer;

    public void transform(final Car car) throws IOException {
        switch (car.getType()) {
            case OFFROAD:
                OffroadCar offroadCar = this.transformer.transform(car);

                // do something with offorad car

                break;
            ...
        }
    }
}

В такой класс Mockito внедрит макет, и выполнение метода будет использовать этот макет, созданный Mockito.

Если вы этого не сделаете хотите использовать эту настройку, тогда вы можете изучить что-то вроде , имитирующего конструктор вашего OffroadTransformer.

С другой стороны, однако, это довольно распространенная практика для factory такие классы, как OffroadTransformer, не имеют состояния и используются как одиночные. Поэтому более естественно следовать описанной выше настройке и позволить Mockito сделать инъекцию за вас.

...