SpyBean не вводится везде - PullRequest
       6

SpyBean не вводится везде

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

Мне трудно вставить шпионский компонент в мой ApplicationContext. У меня есть компонент с именем Утилиты типа Утилиты :

@Component("utilities")
public class Utilities {

<snip>

    /**
     * Returns a random int. This is provided mostly for testing mock-ability
     *
     * @return a random integer
     */
    public int getRandom() {
        return (int) (Math.random() * Integer.MAX_VALUE);
    }
}

И он используется внутри класса, на который косвенно ссылается мой поток Spring Integration.

Тогда у меня есть этот тест Юпитера:

@TestInstance(Lifecycle.PER_CLASS)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@ExtendWith(SpringExtension.class)
@ContextConfiguration( classes = {
    XmlLocations.class,
    VisitorManager.class,
    Utilities.class,
    UnixTimeChannel.class
})
@WebMvcTest
//@TestExecutionListeners( { MockitoTestExecutionListener.class })
public class FullIntegrationTest {

    @Autowired
    private MockMvc mvc;

    @SpyBean
    private Utilities utilities;

    private ClientAndServer mockServer;

    private static final int MOCK_SERVER_PORT = 9089;

    @BeforeAll
    public void setUpBeforeClass() {

        Mockito.when(utilities.getRandom()).thenReturn(Integer.MAX_VALUE);

        mockServer = ClientAndServer.startClientAndServer(MOCK_SERVER_PORT);
        RestAssuredMockMvc.mockMvc(mvc);
        (new MockServerPingInit()).initializeExpectations(mockServer);
        (new MockServerFullIntegrationInit()).initializeExpectations(mockServer);
    }

    @Test
    public void t00200_IncomingMessage() {

        RestAssuredMockMvc.given()
            .queryParam("example", "example")
            .when()
            .request("POST", "/api/v1/incoming")
            .then()
            .statusCode(equalTo(200));
    }

<snip>

Но даже несмотря на то, что я создаю шпионский боб и использую его, когда / thenReturn, он не попадает в контекст моего приложения, ожидая вызова, и возвращает его имитированное случайное значение.

Я знаю, что вызывается метод utilities.getRandom (), потому что я могу поставить на него точку останова и отладить тест, и он попадает в метод getRandom, но когда я пытаюсь добавить шпионский компонент, как показано выше, и макетировать getRandom возвращает фиксированное значение для тестирования точек останова, поэтому я могу сказать, что реальный метод, а не mock, вызывается.

Я также пытался поместить в тест тест if / thenReturn, если это слишком рано, но это не помогает.

Очевидно, что я делаю что-то не так, возможно, концептуально неправильно. Halp!

Ответы [ 2 ]

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

Ладно, спасибо всем за попытки помочь. Не имея смысла расстраивать, публикация конфигурации и потока не поможет, я думаю, из-за того, что я нашел ниже:

При ближайшем рассмотрении произошло исключение:

org.springframework.expression.AccessException: Could not resolve bean reference against BeanFactory

Речь шла о методе внутри утилит, который я использовал в @SpyBean:

    <int:transformer
        expression="@utilities.asMap('licence_id', headers[licenceId], 'message', 'Delivered: ' + headers[confirmedMessage], 'secured_session_id', headers[visitorSession].getSecureSessionId())" />

Это не отдельный ApplicationContext, а SpEL, скорее всего, не примет шпионский компонент, поскольку ссылка изменилась или похожа.

Итак, я оставил утилиты в покое и модифицировал другой внутренний компонент для этого, чтобы генерировать числа, и использовал SpyBean для этого. Теперь Spring Integration / SpEL снова доволен, потому что служебный компонент, с которым он работает, корректен, и насмешка происходит внутри этого компонента и прозрачно для SpEL.

@Component
public class RandomSupplier implements Supplier<Double> {

    @Override
    public Double get() {
        return Math.random();
    }
}

public class FullIntegrationTest {

    @Autowired
    private MockMvc mvc;

    @SpyBean
    private RandomSupplier randomSupplier;

    @Autowired // This is only necessary for the toy test below
    private Utilities utilities;

    @BeforeEach
    public void setupAfterInit() {

        Mockito.when(randomSupplier.get()).thenReturn(0.5);
    }

    @Test
    public void t0() throws IOException {
      System.out.println(utilities.getRandom());
    }
...

Теперь Spring Integration / SpEL снова счастлив, потому что служебный бин, с которым он работает, корректен, и насмешка происходит внутри этого бина.

Три урока: не следите за компонентами, на которые непосредственно ссылаются в SpEL, в Spring Integration Flow; Читать журналы; У вас никогда не может быть достаточно косвенного обращения:)

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

Я попытался воссоздать вашу проблему с минимальной конфигурацией:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {Ctx.class})
public class XTest {

  @SpyBean
  private Random random1;

  @Autowired private Supplier<Integer> intSupplier;

  @Test
  public void test() {
    Mockito.when(random1.nextInt()).thenReturn(Integer.MAX_VALUE);
    int i = intSupplier.get();
    System.out.println("i=" + i);
  }

  @Configuration
  public static class Ctx {

    @Bean
    static Random random1() {
      return ThreadLocalRandom.current();
    }

    @Bean
    static Supplier<Integer> intSupplier(Random random1) {
      return random1::nextInt;
    }
  }
}

И, как и ожидалось, печатает

i=2147483647

Итак, должна быть проблема с вашей конфигурацией времени выполнения ... Не могли бы вы поделиться этим? Я предполагаю, что весенняя интеграция использует другой ApplicationContext. Я знаю, что это не ответ, и я удалю его, если это не поможет.

...