Проблемы с изучением заглушки и насмешек: не удается связать смоделированный класс с модульным тестом - PullRequest
0 голосов
/ 18 июня 2019

Сначала у меня общий вопрос о насмешках и окурках. Я не вижу разницы между этими двумя словами. Вот что я знаю до сих пор: Когда создается модульный тест, а тестируемый метод вызывает метод из другого класса, следует использовать фиктивный объект. Класс, содержащий вызываемый метод, должен быть пересмотрен. Теперь я должен решить, буду ли я издеваться или окуриваться.

Mocking: я просто проверяю, вызывает ли тестируемый мной метод другой метод из mocked-класса.

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

Я почти уверен, что я не совсем понял насчет насмешек и окурков. Вероятно, поэтому я не могу решить следующую проблему самостоятельно.

Вот метод, для которого я хочу создать UnitTest. getCharge находится в классе под названием Movie:

    double getCharge(int daysRented) {
        return price.getCharge(daysRented);
    }

Вот несколько важных кодов класса Movie:

public class Movie {

    public static final int CHILDRENS = 2;
    public static final int REGULAR = 0;
    public static final int NEW_RELEASE = 1;

    private Price price;

    private String title;

    public Movie(String title, int priceCode) {
        if (title == null) {
            throw new IllegalArgumentException("Title cannot be null");
        } else if (title.isBlank()) {
            throw new IllegalArgumentException("Title cannot be empty");
        }
        this.title = title;
        this.setPriceCode(priceCode);
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        if (title == null) {
            throw new IllegalArgumentException("Title cannot be null");
        } else if (title.isBlank()) {
            throw new IllegalArgumentException("Title cannot be empty");
        }
        this.title = title;
    }

    double getCharge(int daysRented) {
        return price.getCharge(daysRented);
    }

    public void setPriceCode(int priceCode) {
        switch (priceCode) {
        case REGULAR:
            price = new RegularPrice();
            break;
        case CHILDRENS:
            price = new ChildrensPrice();
            break;
        case NEW_RELEASE:
            price = new NewReleasePrice();
            break;
        default:
            throw new IllegalArgumentException("Incorrect Price Code");
        }
    }

    public int getFrequentRenterPoints(int daysRented) {
        if (daysRented <= 0) {
            throw new IllegalArgumentException("Rented days have to be more than 0.");
        }
        return price.getFrequentRenterPoints(daysRented);
    }

}

Поскольку я делаю юнит-тест, я не хочу использовать логику ценового класса. Поэтому я высмеиваю ценовой класс и определяю, что должен вернуть метод getCharge-метода ценового класса:

    @Test
    public void testGetCharge() {
        // given
        Price mockedPrice = Mockito.mock(Price.class);
        when(mockedPrice.getCharge(3)).thenReturn(3.0);
        // when
        double expected = 3.0;
        double actual = movie.getCharge(3);

        assertEquals(expected, actual);

    }

Очевидно, что это не сработает, потому что я не связал свою mockedPrice с объектом цены в моем классе Movie. Проблема в том, что я могу установить объект цены только с помощью setPriceCode (см. Конструктор класса Movie). И вот где я застрял. Есть ли какое-либо решение для установки цены без создания другого метода установки?

1 Ответ

0 голосов
/ 18 июня 2019

Mockito предлагает аннотацию @InjectMocks, которая делает некоторую магию отражения и «выталкивает» любое поле вашего теста, помеченное @Mock, в тестируемый класс. См. здесь для некоторых указаний.

@ InjectMocks немного сложнее, так как он не дает никаких подсказок, когда не справляется со своей работой, тогда он просто не внедряет макет объекта, и вы продолжаете задаваться вопросом, почему ваши тесты ведут себя странным образом.

Альтернативой использованию этой аннотации является «другой способ внедрения зависимостей», например, с помощью конструктора, который принимает объект (ы), который вам нужно смоделировать для тестов.

Относительно насмешек против окурков ... на самом деле нет точных определений для этих двух слов. Вы можете получить некоторые идеи здесь например. Там вам говорят, что издевательствам нужно указать, что возвращать, например. Что не обязательно верно для mockito, так как Mockito будет возвращать некоторые значения по умолчанию, когда вы вызываете метод, возвращающий значение для фиктивного объекта (например, null или 0).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...