Я пытаюсь написать набор интеграционных тестов для проекта, который не написал, и не хочу менять реализацию какого-либо кода. Теперь в этом коде есть класс 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 Я знаю другой способ сделать это, чтобы изолировать создание объектов на фабрике и смоделировать эту фабрику, но я не хочу менять какие-либо из существующих код вообще.