mockito SpyBean不是到处注射

v2g6jxz6  于 9个月前  发布在  其他
关注(0)|答案(2)|浏览(63)

我很难将间谍bean放入我的ApplicationContext。我有一个名为 utilities 的bean,类型为 Utilities

@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>

但是,即使我创建了间谍bean并在其上使用了when/thenReturn,它也不会浮动到我的应用程序上下文中,等待被调用并返回其模拟的随机值。
我知道方法utilities.getRandom()会被调用,因为我可以在它上面放置一个断点并调试测试,它会命中getRandom方法,但是当我尝试添加如上所示的间谍bean并模拟getRandom以返回一个固定值用于测试时,断点仍然会命中,因此我可以告诉真实的方法,而不是mock被调用。
我也试过把when/thenReturn放在测试中,以防太早,但没有帮助。
很明显我做错了,可能是概念上的错误。哈普!

14ifxucb

14ifxucb1#

我试图用最小的配置重现你的问题:

@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

所以,你的运行时配置一定有问题...你能分享一下吗我猜spring-integration正在使用另一个ApplicationContext。我知道这不是答案,如果没有帮助,我会删除它。

dy1byipe

dy1byipe2#

好的,谢谢你们的帮助。我不想让人沮丧,我认为发布配置和流程不会有帮助,因为我发现了下面的内容:
仔细观察有一个例外:

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不会接受间谍bean,因为引用已经更改或类似。
因此,我不去管这些实用程序,而是在其内部改造了另一个bean来生成数字,并在其上使用SpyBean。现在Spring Integration/SpEL又高兴了,因为它使用的实用程序bean是正确的,并且mocking发生在bean内部,对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又高兴了,因为它正在工作的实用程序bean是正确的,并且mocking发生在该bean内部。
三个教训:不要在Spring集成流中窥探SpEL中直接引用的bean;阅读日志;你永远不会有足够的间接:)

相关问题