Ложный метод, который вызывается внутри другого метода - PullRequest
0 голосов
/ 25 сентября 2018

Я пытаюсь использовать Powermock для имитации вызовов в базу данных.Вот пример того, как выглядит наш код:

public class WrapperClass {
    public static SearchUtil searchUtil = new SearchUtil();
}

public class SearchUtil {
    public Record searchForThing(String thing) {
        // Makes a call to a database and returns a record
    }
}

public class TestableClass {
    public void runMethod() {
        // When this is called, it returns null, however based on the debugger, WrapperClass.searchUtil is a mocked object
        WrapperClass.searchUtil.searchForThing("thing");
    }
}

@PrepareForTest(WrapperClass.class)
@PowerMockIgnore({"javax.management.*", "javax.xml.parsers.*", "com.sun.org.apache.xerces.internal.jaxp.*", "ch.qos.logback.*", "org.slf4j.*", "org.apache.xerces.*", "javax.xml.*", "org.xml.sax.*", "org.w3c.dom.*"})
@RunWith(PowerMockRunner.class)
public class MyTest {
    @Test
    public void runMyTest() {
        SearchUtil searchUtil = PowerMockito.mock(SearchUtil.class);
        PowerMockito.mockStatic(WrapperClass.class);
        Whitebox.setInternalState(WrapperClass.class, "searchUtil", searchUtil);
        PowerMockito.doReturn(new SearchRecord()).when(WrapperClass.searchUtil).searchForThing("thing");

        // When the below call is made, a new SearchRecord is returned and is not null
        WrapperClass.searchUtil.searchForThing("thing");

        // Calling the method that calls the searchForThing method, when searchForThing is called inside runMethod, it returns null
        new TestableClass().runMethod();
    }
 }

Я знаю, что статическая переменная и тому подобное, безусловно, не лучшая практика, но сейчас давайте представим, что я не могу ее изменить.Когда смоделированный вызов вызывается в тесте, он возвращает новый SearchRecord, как и ожидалось.Когда он вызывается в runMethod, он возвращает ноль, однако searchUtil объект является смоделированным объектом согласно моему отладчику.Почему такое поведение происходит, когда вызов метода stubbed является вложенным?

1 Ответ

0 голосов
/ 25 сентября 2018

Просмотрите следующее, которое должно вести себя как ожидалось.

@PowerMockIgnore({"javax.management.*", "javax.xml.parsers.*", "com.sun.org.apache.xerces.internal.jaxp.*", "ch.qos.logback.*", "org.slf4j.*", "org.apache.xerces.*", "javax.xml.*", "org.xml.sax.*", "org.w3c.dom.*"})
@RunWith(PowerMockRunner.class)
@PrepareForTest(WrapperClass.class, TestableClass.class)
public class MyTest {
    @Test
    public void runMyTest() {
        //Arrange 
        Record expected = new SearchRecord();
        String arg = "thing";
        SearchUtil searchUtil = PowerMockito.mock(SearchUtil.class);
        when(searchUtil.searchForThing(arg)).thenReturn(expected);

        // mock all the static members in WrapperClass class
        PowerMockito.mockStatic(WrapperClass.class);
        // use Mockito to set up your expectation
        when(WrapperClass.searchUtil).thenReturn(searchUtil);

        TestableClass subject = new TestableClass();

        //Act
        subject.runMethod();

        //Assert
        //...
    }
 }

Обратите внимание на ход теста.

Я бы также предложил удостовериться, что аргумент, используемый в тесте, совпадает с аргументом, переданным используемым методом, потому что, если они этого не делают, он также вернет null из-за несовпадающих аргументов/parameters.

В противном случае вам нужно будет ослабить сопоставление аргументов

//...

when(searchUtil.searchForThing(any(String.class))).thenReturn(expected);

//...

Вы также можете просмотреть документы powermock-mockito здесь для лучшего понимания того, какиспользуйте рамки.

...