Использование PowerMock во время инициализации контекста Spring - PullRequest
0 голосов
/ 08 января 2020

Я пытаюсь написать набор интеграционных тестов для проекта, который не написал, и не хочу менять реализацию какого-либо кода. Теперь в этом коде есть класс SalesforceSubscriptionManager, который представляет собой Spring Bean (компонент), вызывающий конструктор для SalesforceBusSubscriber.

@Component
public class SalesforceSubscriptionsManager {
    public SalesforceSubscriptionsManager() {
        System.out.println("creating bean");
        //implementation remove for brevity
        new SalesforceBusSubscriber(credentials, consumer);
    }
}

Я пытаюсь создать экземпляр класса SalesforceBusSubscriber, поэтому, когда приложение контекст настроен, и бин создан, он не использует реальный класс подписчика. Для этого я использую PowerMock. Вот как выглядят мои тесты:

@SpringBootTest
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@ContextConfiguration(
        classes = {Application.class},
        initializers = { ConfigFileApplicationContextInitializer.class, SalesforceBusSubscriber.class }
)
@PrepareForTest({SalesforceBusSubscriber.class})
@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "javax.xml.transform.*", "org.xml.*", "javax.management.*", "javax.net.ssl.*", "com.sun.org.apache.xalan.internal.xsltc.trax.*"})
public class BaseTest {
    @ClassRule
    public static PreContextMockRule mock = new PreContextMockRule();

    @Test
    public void test() throws Exception {
        SalesforceBusSubscriber postContext = new SalesforceBusSubscriber(
            new SalesforceBusCredentials(1L,"http://www.google.com", "user","pass","d"),
            Mockito.mock(Consumer.class)
        );
    }
}

Правило, которое я создал, выглядит так:

/**
 * Rule to allow powermock behaviour before spring context is initiated so that when the context
 * runs they are already applied.
 */
public class PreContextMockRule extends ExternalResource {
    protected void before() throws Throwable {
        System.out.println("running rule");

        SalesforceBusSubscriber mockSubscriber = mock(SalesforceBusSubscriber.class);

        whenNew(SalesforceBusSubscriber.class)
                .withArguments(any(SalesforceBusCredentials.class), any(AbstractConsumer.class))
                .thenReturn(mockSubscriber);

        when(mockSubscriber.getErrorFlag()).thenReturn(false);
    }

    protected void after() {
        System.out.println("after");
    }
}

Теперь, когда я строю свой код и запускаю, я вижу следующее:

running rule
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot :: 

//more stuff

creating bean

Таким образом, powermock работает до того, как контекст запущен, контекст загружается, а затем создается компонент. Однако при пошаговом выполнении кода SaleforceBusSubscriber в конструкторе не является имитацией, а метод с именем "postContext" в методе с именем "test" является имитацией ...

У меня вопрос: как я могу сделать powermock? издеваться над созданием новых объектов в Spring Bean?

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

...