我正在编写一个边线微服务,它将TCP与传统应用程序进行对话,并在另一方使用rabbitMQ。我正在开始编写测试,因为我一直在更好地理解一切是如何工作的,因为我是Spring的新手。我的应用程序构建,部署和运行正常。
但是,编写干净的测试要复杂一些。我一直在使用spring-integration tcp基本示例模拟我的代码。我开始使用模拟TCPServer来测试我在测试类之外定义的代码。但是模拟的TCPServer仍然是为每个测试类而构建的。所以我把它移到TCPGatewayTest类中,类似于示例I found。
这导致了一些缺少bean的问题,导致我添加了@ContextConfiguration注释,这让我更进一步。但是现在我还有其他缺豆。我确定我用@ContextConfiguration弄乱了我的ApplicationContext。是否有更好的方法使用不同的注释或略微不同的方式执行此操作?我没有走xml路线,如果可能的话,我想避开它。
熟悉的没有限定bean错误:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.amqp.rabbit.connection.ConnectionFactory' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
我的测试类如下
package org.inc.imo;
@ComponentScan("org.inc")
@ContextConfiguration(classes = {TCPGatewayTest.TCPServerMock.class,
org.inc.imo.Configuration.TCPConfig.class,
org.inc.imo.Configuration.RabbitConfig.class })
@TestPropertySource(locations= "classpath:test.properties")
@RunWith(SpringRunner.class)
@SpringBootTest
public class TCPGatewayTest {
@Autowired
private TCPGateway gateway;
@Autowired
AbstractServerConnectionFactory crLfServer;
@Before
public void setup() {
TestingUtilities.waitListening(this.crLfServer, 10000L);
}
@Test
public void testConnectionToMockServer() {
String result = gateway.send("Hello World");
assertEquals("HELLO WORLD", result);
}
@Configuration
@MessageEndpoint
public static class TCPServerMock {
@Value("${imo.port}")
private int port;
@Bean()
public AbstractServerConnectionFactory serverCF() {
return new TcpNetServerConnectionFactory(this.port);
}
@Transformer(inputChannel="fromTcp", outputChannel="toEcho")
public String convert(byte[] bytes) {
return new String(bytes);
}
@ServiceActivator(inputChannel="toEcho")
public String upCase(String in) {
return in.toUpperCase();
}
@Bean
public TcpInboundGateway tcpInGate(AbstractServerConnectionFactory connectionFactory) {
TcpInboundGateway inGate = new TcpInboundGateway();
inGate.setConnectionFactory(connectionFactory);
inGate.setRequestChannel(fromTcp());
return inGate;
}
@Bean
public MessageChannel fromTcp() {
return new DirectChannel();
}
}
}
Rabbit Config Class
package org.inc.imo.configuration;
@EnableIntegration
@IntegrationComponentScan
@ComponentScan
@Configuration
public class RabbitConfig {
public final static String IMO_REQUEST_JEA = "imo.request.jea";
public final static String IMO_REQUEST_INFO = "imo.request.info";
@Bean
public AmqpAdmin amqpAdmin(final ConnectionFactory connectionFactory) {
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
admin.declareQueue(jeaRequestQueue());
admin.declareQueue(infoRequestQueue());
return admin;
}
@Bean
public Queue jeaRequestQueue() {
return new Queue(IMO_REQUEST_JEA);
}
@Bean
public Queue infoRequestQueue() {
return new Queue(IMO_REQUEST_INFO);
}
@Bean
public RabbitTemplate rabbitTemplate(final ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
return rabbitTemplate;
}
@Bean
public ObjectWriter objectWriter() {
return new ObjectMapper().writer();
}
}
TCPConfig类
package org.inc.imo.configuration;
@EnableIntegration
@IntegrationComponentScan
@ComponentScan
@Configuration
public class TCPConfig {
@Value("${imo.hostname}")
private String host;
@Value("${imo.port}")
private int port;
private static MessageChannel sendChannel;
private static MessageChannel replyChannel;
@Bean
public MessageChannel replyChannel() {
replyChannel = new DirectChannel();
return replyChannel;
}
@Bean(name="sendChannel")
public MessageChannel sendChannel() {
MessageChannel directChannel = new DirectChannel();
sendChannel = directChannel;
return directChannel;
}
@Bean
public TcpNetClientConnectionFactory connectionFactory() {
TcpNetClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory(host, port);
connectionFactory.setSingleUse(false);
return connectionFactory;
}
@Bean
@ServiceActivator(inputChannel = "sendChannel")
public TcpOutboundGateway tcpOutboundGateway() {
TcpOutboundGateway tcpOutboundGateway = new TcpOutboundGateway();
tcpOutboundGateway.setConnectionFactory(connectionFactory());
tcpOutboundGateway.setReplyChannel(this.replyChannel());
tcpOutboundGateway.setRequiresReply(true);
return tcpOutboundGateway;
}
}
TCPGateway接口
package org.inc.imo.Domain;
@MessagingGateway(defaultRequestChannel = "sendChannel")
public interface TCPGateway {
String send(String message);
}
答案 0 :(得分:1)
例外情况如下:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.amqp.rabbit.connection.ConnectionFactory' available: expected at least 1 bean which qualifies as autowire candidate.
受苦的豆子就像:
@Bean
public AmqpAdmin amqpAdmin(final ConnectionFactory connectionFactory) {
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
admin.declareQueue(jeaRequestQueue());
admin.declareQueue(infoRequestQueue());
return admin;
}
所以,你在这里请求org.springframework.amqp.rabbit.connection.ConnectionFactory
bean注入,但是没有人注入。
如果您只是针对本地RabbitMQ进行测试,那么只需添加一个bean:
@Bean
ConnectionFactory connectionFactory() {
return new CachingConnectionFactory();
}
并且您的AmqpAdmin
将能够在那里连接。