spring integration advice afterReceive method not called in unit test

huangapple go评论59阅读模式
英文:

spring integration advice afterReceive method not called in unit test

问题

你的问题是你的EmptyFolderAdvice类中的afterReceive方法从未被调用。这可能是由于配置或测试问题引起的。以下是一些建议来排查问题:

  1. 确保你的配置文件FlowConfiguration中正确地配置了emptyFolderAdvice()作为定期调度器(PollerMetadata)的建议(advice)。你的配置看起来是正确的,但要确保没有其他地方覆盖了这个配置。

  2. 在你的测试类StopApplicationTest中,确保EmptyFolderAdvice类的bean(advice)被正确注入。你可以在测试方法中添加一些日志或断言来确认它是否已成功注入。

  3. 确保你的测试方法的消息(message)实际上被发送到了inputChannel。你可以添加日志来检查消息是否被发送,并确保在发送消息之后等待一些时间以确保方法被调用。

  4. 如果仍然存在问题,检查是否有其他配置或切面可能会影响建议(advice)的调用。可能会有其他方面或拦截器干扰了建议的执行。

通过检查这些方面,你应该能够找到为什么EmptyFolderAdviceafterReceive方法没有被调用的原因。如果问题仍然存在,请提供更多详细信息,以便我可以提供更多帮助。

英文:

Hello i'am trying to add an advice to handle the case of empty files in a directory , the use case is when the directory is empty we should stop the application which is a springbok application .

here is my configuration file :

@Configuration
public class FlowConfiguration {

	private static final Logger LOGGER = LoggerFactory.getLogger(FlowConfiguration.class);

	@Bean("creFileInboundChannel")
	MessageChannel fileInputChannel() {
		return new DirectChannel();
	}

	@Bean(name = PollerMetadata.DEFAULT_POLLER)
	public PollerMetadata poller() {
		return Pollers.fixedRate(1000)
					  .advice(emptyFolderAdvice())
					  .get();
	}

	@Bean
	DirectoryScanner directoryScanner(@Value("${inbound.filename.regex:.*}") String regex) {
		RecursiveDirectoryScanner scanner = new RecursiveDirectoryScanner();
		CompositeFileListFilter filter = new CompositeFileListFilter<>(
				Arrays.asList(new AcceptOnceFileListFilter<>(),
						new RegexPatternFileListFilter(regex))
		);
		scanner.setFilter(filter);
		return scanner;
	}

	@Bean
	@InboundChannelAdapter(value = "creFileInboundChannel", poller = @Poller(fixedDelay = "1000"))
	MessageSource<File> fileReadingMessageSource(DirectoryScanner directoryScanner, CreConfiguration creConfiguration) {
		FileReadingMessageSource source = new FileReadingMessageSource();
		source.setDirectory(new File(creConfiguration.getInputDir()));
		source.setScanner(directoryScanner);
		return source;
	}

	@Bean
	@ServiceActivator(inputChannel = "creOutputChannel")
	MessageHandler logOutputCreFileHandler() {
		return message -> {
			if (message.getPayload() instanceof Optional) {
				Optional<File> filteredFile = (Optional<File>) message.getPayload();

				if (filteredFile.isPresent()) {
					LOGGER.info("end of process {}, writing file in the output directory", filteredFile.get());
				}
			}
		};
	}

	@Bean
	@ServiceActivator(inputChannel = "creFileInboundChannel")
	MessageHandler creFileInFolderHandler(TraitementCreService traitementCreService) {
		List<Advice> advices = new ArrayList<>();
		advices.add(emptyFolderAdvice());
		ServiceActivatingHandler serviceActivatingHandler = new ServiceActivatingHandler(traitementCreService, "invoke");
		serviceActivatingHandler.setOutputChannelName("creOutputChannel");
		serviceActivatingHandler.setAdviceChain(advices);
		return serviceActivatingHandler;
	}

	@Bean
	@ServiceActivator(inputChannel = "errorChannel")
	MessageHandler erreurHandler() {
		return message ->
				LOGGER.info("Error when treating file : {}", ((ErrorMessage) message).getOriginalMessage().getPayload());
	}

	@Bean("errorChannel")
	QueueChannel errorChannel() {
		return new QueueChannel(500);
	}

	@Bean
	public EmptyFolderAdvice emptyFolderAdvice() {
		return new EmptyFolderAdvice();
	}

}

here is my advice class that handles shutdown when directory is empty :

public class EmptyFolderAdvice extends AbstractMessageSourceAdvice {


	@Override
	public Message<?> afterReceive(Message<?> message, MessageSource<?> source) {
		File directory = (File) source;
		File[] files = directory.listFiles();
		if (files == null || files.length == 0) {
			System.exit(0); // Stop the application if no files exist
		}
		return message;
	}
}

here is my integration test :

@SpringIntegrationTest
@SpringBootTest
@ContextConfiguration(classes = FiltrageApp.class)//{FlowConfiguration.class, FiltrageConfiguration.class})
public class StopApplicationTest {

	@MockBean
	private EmptyFolderAdvice advice; // Inject the advice under test

	@Qualifier("creFileInboundChannel")
	@Autowired
	private MessageChannel inputChannel;

	@MockBean
	TraitementCreService traitementCreService;

	@Autowired
	private MessageSource<?> messageSource;

	@Autowired
	private ApplicationContext context;

	@Autowired
	private MessageHandler creFileInFolderHandler;

	@Test
	public void testAfterReceiveIsCalled() throws TechnicalException {

		// Create a test message
		Message<?> message = MessageBuilder.withPayload("").build();

		// Send the message to the input channel
		//traitementCreService.invoke(null);
		inputChannel.send(message);

		traitementCreService.invoke(null);
		// Verify that the afterReceive method is called
		Mockito.verify(advice).afterReceive(Mockito.any(Message.class), Mockito.any(MessageSource.class));

		// You can also verify the number of times the method is called, e.g., Mockito.verify(mockAdvice, Mockito.times(1)).afterReceive(...)
	}

my problem is that is does not work and the afterReceive method of the advice is never called.

thanks

答案1

得分: 1

你在配置中使用了显式的轮询器:

@InboundChannelAdapter(value = "creFileInboundChannel", poller = @Poller(fixedDelay = "1000"))

但是你应用了emptyFolderAdvice(),它是没有用的。

你仍然需要一个PollerMetadata bean,但它不能是PollerMetadata.DEFAULT_POLLER,并且在@Poller中使用它的名称:

/**
 * @return {@link org.springframework.integration.scheduling.PollerMetadata} bean 的名称。
 */
String value() default "";

你的EmptyFolderAdvice中的逻辑也是错误的:

public Message<?> afterReceive(Message<?> message, MessageSource<?> source) {
    File directory = (File) source;

如何将MessageSource 强制转换为 File

你只需要检查 message == null:如果没有要从 FileReadingMessageSource 中生成的文件,那么会调用此 afterReceive() 方法,并且 message 会为 null

英文:

You use an explicit poller in your configuration:

@InboundChannelAdapter(value = &quot;creFileInboundChannel&quot;, poller = @Poller(fixedDelay = &quot;1000&quot;))

But you apply your emptyFolderAdvice() which is out of use.

You still need to have a PollerMetadata bean, but that must not be a PollerMetadata.DEFAULT_POLLER and use its name in the @Poller:

/**
 * @return The {@link org.springframework.integration.scheduling.PollerMetadata} bean
 * name.
 */
String value() default &quot;&quot;;

The logic in your EmptyFolderAdvice is also wrong:

public Message&lt;?&gt; afterReceive(Message&lt;?&gt; message, MessageSource&lt;?&gt; source) {
    File directory = (File) source;

How a MessageSource can be casted to a File?

You just need to check for message == null: if no files to produce from a FileReadingMessageSource, then this afterReceive() method is called with null.

huangapple
  • 本文由 发表于 2023年6月21日 22:48:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76524591.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定