java.lang.NullPointerException возникает из-за того, что свойство не загружается в Mockito при насмешке над методом

Я новичок в Mockito, и у меня возникла проблема из-за того, что свойство не загружается из файла appication.properties.

Постановка проблемы: я пытаюсь смоделировать метод, который использует свойство из файла application.properties. Когда элемент управления достигает строки для загрузки значения свойства, он показывает null, и из-за этого mockito выдает java.lang.NullPointerException.

Я ищу, как загрузить свойство из файла application.properties при насмешке над методом. Здесь я пытаюсь загрузить глобальную переменную partsListGlobal. Пожалуйста, помогите мне, как это сделать.?

Вот мой фрагмент кода ниже.

@Service
public class ClimoDiagnosticReportServImpl implements ClimoDiagnosticReportService {

    @Value("${PARTS_LIST}")
    private String partsListGlobal;

    @Override
    public boolean getSomeResult() {
        String[] partsListLocal = getPartsList();

        List<String> partsList = Arrays.asList(partsListGlobal);

        if (partsList.contains("PART_X1"))
            return true;
        else
            return false;
    }

    public String[] getPartsList() {
        return partsListGlobal.split(",");// Here is the error occuring due to partsListGlobal is not loading the value from application.properties file.
    }
}

@RunWith(MockitoJUnitRunner.class)
public class ClimoDiagnosticReportServImplTest {

    @InjectMocks
    private ClimoDiagnosticReportServImpl serviceReference1;

    @Mock
    private ClimoDiagnosticReportServImpl serviceReference12;

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

    @Test
    public void getSomeResultTest() {

        boolean result1 = false;
        String[] strArray = new String[2];
        strArray[0] = "P1";
        strArray[1] = "P2";
        Mockito.when(serviceReference12.getPartsList()).thenReturn(strArray);
        boolean result2 = serviceReference1.getSomeResult();
        Assert.assertEquals(result1,result2);

    }
}

Ошибка:

Спасибо всем заранее.

У вас нет никакой зависимости от mock в сервисе. Таким образом, Mockito совершенно не нужен. Что вам нужно сделать, так это установить поле private String, которое заполняется Spring в вашем приложении с использованием отражения.


person user3884306    schedule 29.12.2018    source источник
comment
Используйте внедрение конструктора вместо внедрения поля и передайте любое значение String, которое вы хотите, конструктору в вашем модульном тесте.   -  person Fullstack Guy    schedule 29.12.2018
comment
Почему у тебя два _1_ ? _2_ — это Служба, которую вы хотите протестировать, но как насчет _3_? _4_ — имитировать зависимости (поля _5_) вашего сервиса, но у вас нет никакой зависимости.   -  person JB Nizet    schedule 29.12.2018
comment
@Ricola, ты имеешь в виду, что нет необходимости использовать serviceReference12 ..? скорее использовать только serviceReference1..?   -  person Ricola    schedule 29.12.2018
comment
Мой вопрос скорее: что вы хотите сделать с _1_?   -  person user3884306    schedule 30.12.2018
comment
Спасибо за драгоценный вклад. Но у меня есть небольшая проблема, что, если у меня слишком много свойств для загрузки из файла application.properties ..? Должен ли по-прежнему следовать той же инъекции конструктора ..?   -  person Ricola    schedule 30.12.2018


Ответы (1)


Просто следуйте наилучшей практике ОС, используя внедрение cnstructor вместо внедрения поля, и это сделает ваш код тестируемым (это одна из причин, почему это лучшая практика):

Теперь ваш тест можно сократить до

@Service 
public class ClimoDiagnosticReportServImpl implements ClimoDiagnosticReportService {

    private String partsListGlobal;

    public ClimoDiagnosticReportServImpl(@Value("${PARTS_LIST}") String partsListGlobal) {
        this.partsListGlobal = partsListGlobal;
    }

    // ...
}

Возможный дубликат Как мне издеваться над поле @Value autowired в Spring с Mockito?

public class ClimoDiagnosticReportServImplTest {

    @Test
    public void shouldReturnTrueIfPropertyContainsPartX1() {
        ClimoDiagnosticReportServImpl service = new ClimoDiagnosticReportServImpl("a,b,c,PART_X1,d");
        assertTrue(service.getSomeResult());
    }

    @Test
    public void shouldReturnFalseIfPropertyDoesNotContainPartX1() {
        ClimoDiagnosticReportServImpl service = new ClimoDiagnosticReportServImpl("a,b,c,d");
        assertFalse(service.getSomeResult());
    }
}
person JB Nizet    schedule 29.12.2018
comment
Если bean-компонент зависит от стольких свойств, это, вероятно, означает, что у него слишком много обязанностей, и его следует разделить на несколько bean-компонентов. В общем, если у вас есть несколько свойств, касающихся данной функциональности, вы должны использовать POJO, объединяющий все эти свойства и аннотированный с помощью ConfigurationProperties. И введите этот POJO в свой компонент. документы .spring.io/spring-boot/docs/current/reference/htmlsingle/ - person user3884306; 29.12.2018
comment
java.lang.NullPointerException в com.test.serviceimpl.ClimoDiagnosticReportServImpl.getPartsList(ClimoDiagnosticReportServImpl.java:68) в com.test.serviceimpl.ClimoDiagnosticReportServImpl.getSomeResult(ClimoDiagnosticReportServImpl.java:57) в com.test.Tgnomest.serviceimpl.ClimoDiagnostic ClimoDiagnosticReportServImplTest.java:74) в sun.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) в sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl) в.java:4mpl .lang.reflect.Method.invoke(Method.java:498) в org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) в org.junit.internal.runners.model.ReflectiveCallable.run( ReflectiveCallable.java:12) на org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) на org.junit.internal.runners.sta tements.InvokeMethod.evaluate(InvokeMethod.java:17) в org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) в org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) в org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) в org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) в org.junit.runners.ParentRunner$3.run(ParentRunner.java: 290) в org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) в org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) в org.junit.runners.ParentRunner.access$000(ParentRunner .java:58) в org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) в org.junit.runners.ParentRunner.run(ParentRunner.java:363) в org.mockito.internal.runners.JUnit45AndHigherRunnerImpl .run(JUnit45AndHigherRunnerImpl.java:37) в org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) в org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) в org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) в org.eclipse. jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) в org.eclipse.jdt.internal. junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) на org.eclipse.jdt.internal.junit.runner. RemoteTestRunner.main(RemoteTestRunner.java:192) - person JB Nizet; 29.12.2018