Java Mockito использует реальный метод, а не фиктивный метод

Мой метод mockito поражает реальный метод, а не вызывает издевательский метод. Ваши отзывы будут полезны

Код Java.

public class CheckUser {
    private final UserDao userDao;

    public CheckUser (final String domain){
        userDao = new UserDao(domain);
    }

    public IUser getExistingUser(){
            if (userDao == null) {
                throw new RuntimeException("userDao is null");
            }
            IUser existingUser = userDao.getExistingUser();
            if (existingUser == null) {
                throw new RuntimeException("ExistingUser is null");
            }
            return existingUser;
    }
}

Это мой тестовый код JUnit.

    @Test
    public void testExistingUser() {
        UserDao mockUserDao = mock(UserDao.class);
        when(mockUserDao.getExistingUser()).thenReturn(getExistingTestUser());
    }

    private UserDao getExistingTestUser(() {
        return ExistingUserImpl.Builder(). //withfield methods. build();
    }

Я создаю этот фиктивный объект только для целей тестирования. Это просто возвращает фиктивный объект MockedExistingUserImpl, который реализован IUser.

public class MockedExistingUserImpl implements IUser {
    //fields
    //overriding getter methods for all fields
    //Builder for  ExistingUserImpl
}

Когда я вызываю userDao.getExistingUser () в своем коде, я ожидаю вернуть имитируемый объект Existing user, но он попадает в реальный метод и не проходит тест из-за подключения к домену. Мы не устанавливаем доменное соединение для запуска Junits. Любые входы приветствуются. Спасибо !


person Sunil    schedule 29.05.2019    source источник
comment
Когда я когда-либо вызываю userDao.getExistingUser () в своем коде ›не могли бы вы также опубликовать код модульных тестов, который вызывает это?   -  person Dat Nguyen    schedule 29.05.2019
comment
Это класс для живого использования или класс для тестирования? Потому что это класс для живого использования, в который встроены тесты.   -  person Compass    schedule 29.05.2019
comment
CheckUser - это класс только для живого использования. Остальные созданы для тестирования   -  person Sunil    schedule 29.05.2019
comment
@DatNguyen Nguyen Это мой код Junit @ Test public void testExistingUser () {UserDao mockUserDao = mock (UserDao.class); когда (mockUserDao.getExistingUser ()). thenReturn (getExistingTestUser ()); }   -  person Sunil    schedule 29.05.2019


Ответы (2)


Ваша ошибка в нарушении принципа «Внедрения зависимостей».

Не используйте оператор new - создайте UserDao на уровне выше и используйте инъекцию.

public class CheckUser {
    private final UserDao userDao;

    public CheckUser (final UserDao usedDao) {
        this.userDao = userDao;
    }

    public IUser getExistingUser() {
        if (userDao == null) {
            throw new RuntimeException("userDao is null");
        }
        IUser existingUser = userDao.getExistingUser();
        if (existingUser == null) {
            throw new RuntimeException("ExistingUser is null");
        }
        return existingUser;
    }
}

Теперь вы можете протестировать свой код следующим образом:

@Test
public void testExistingUser() {
    UserDao mockUserDao = mock(UserDao.class);
    when(mockUserDao.getExistingUser()).thenReturn(getExistingTestUser());

    CheckUser checkUser = new CheckUser(mockUserDao);
    IUser iUser = checkUser.getExistingUser();

    // assertions here
}

private UserDao getExistingTestUser(() {
    return ExistingUserImpl.Builder(). //withfield methods. build();
}
person Bor Laze    schedule 29.05.2019
comment
Спасибо за ваш ответ. Что ж, такой подход имеет смысл. Использование оператора new - плохая идея. Это сработает для меня, если я создам свои Junits в отдельном тестовом классе Java. Но мне нужно создать планы тестирования, используя класс parentTestplan. Так что, если я использую его в моем существующем родительском плане тестирования, он потерпит неудачу. Это действительно расстраивает. - person Sunil; 30.05.2019

Ответ - прочитать руководство по Mockito и следовать ему. Вы делаете типичную ошибку: вы создаете фиктивный объект, но затем ничего не делаете, чтобы ваш производственный код использовал этот фиктивный объект.

Простое выполнение mock (YourClass) не меняет волшебным образом этот new () в вашем производственном коде для возврата фиктивного экземпляра.

Вам необходимо внедрить этот фиктивный экземпляр в тестируемый код. Например, используя аннотацию @InjectMock.

Хорошее вступление см. В https://www.baeldung.com/Mockito-annotations для пример.

И обратите внимание: как написано прямо сейчас, вам будет сложно использовать Mockito для ваших тестов. Из-за прямого вызова new () вам понадобится PowerMock (ito) для его тестирования. Итак: узнайте, как использовать Mockito, а затем переработайте свой производственный код, чтобы его можно было легко тестировать. (обращение к PowerMock было бы неправильной стратегией).

person GhostCat    schedule 29.05.2019
comment
Всегда рекомендую перейти к внедрению конструктора, если это применимо. - person chrylis -cautiouslyoptimistic-; 29.05.2019
comment
@chrylis Это спорно. Имея телескопические конструкторы только для тестирования ... ну: реальным решением может быть использование реальной инъекции зависимостей, не основанной на дополнительном ctor, а, в общем, реальной системы внедрения зависимостей. - person GhostCat; 29.05.2019