为了账号安全,请及时绑定邮箱和手机立即绑定

SpyBean 没有被注入到任何地方

SpyBean 没有被注入到任何地方

不负相思意 2021-09-03 14:35:39
我很难将 spy bean 放入我的 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 集成流程间接引用的类中使用的。然后我有这个木星测试:@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>但是即使我创建了 spy bean 并在它上面使用了 when/thenReturn,它也不会漂浮到我的应用程序上下文中等待被调用并返回它的模拟随机值。我知道utilities.getRandom() 方法被调用,因为我可以在它上面放置一个断点并调试测试,并且它命中了getRandom 方法,但是当我尝试添加一个如上所示的间谍bean 并模拟getRandom 时返回一个固定值来测试断点仍然命中,所以我可以告诉真正的方法不是正在调用模拟。我试过将 when/thenReturn 也放在测试中,以防为时过早,但这无济于事。显然我做错了什么,可能在概念上是错误的。呸!
查看完整描述

2 回答

?
四季花海

TA贡献1811条经验 获得超5个赞

好的,谢谢大家的帮助。无意沮丧,发布配置和流程对我的想法没有帮助,因为我在下面发现了:


仔细检查有一个例外:


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 是正确的,并且模拟发生在该 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 是正确的,并且模拟发生在该 bean 内部。


三个教训:不要窥探 Spring Integration Flow 中 SpEL 中直接引用的 bean;阅读日志;你永远不可能有足够的间接性:)


查看完整回答
反对 回复 2021-09-03
?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

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


@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。我知道这不是答案,如果没有帮助,我会删除它。


查看完整回答
反对 回复 2021-09-03
  • 2 回答
  • 0 关注
  • 416 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信