ApplicationEvents 声称通过 TestRestTemplate 调用时未触发我的事件

ApplicationEvents claims my event wasn't fired, when called via TestRestTemplate

提问人:Sören 提问时间:10/12/2023 最后编辑:Sören 更新时间:10/12/2023 访问量:42

问:

我有一个spring boot RestController,它调用一个Service,它触发一个自定义ApplicationEvent。

测试服务时,测试为绿色 - 已正确识别触发的事件。

但是,当我添加一个通过 HTTP 接口测试控制器和服务的测试时,测试是红色的 - 无法识别触发的事件。调试时,我可以看到调用了 SomeService.foo()。那为什么测试会失败呢?

我知道这些测试的结构可能并不理想。这是一个简化的例子,实际应用程序已经有很多这样的“让我们一起测试所有层”的测试,我现在必须坚持这种结构。

版本:spring-boot 3.1.4、Spock 2.4-M1-groovy-4.0

这些是控制器、服务和事件:

package org.example;

import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/")
@AllArgsConstructor
public class SomeController {
    private final SomeService service;

    @PostMapping("/")
    public void foo() {
        service.foo();
    }
}
package org.example;

import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

@Service
@AllArgsConstructor
public class SomeService {
    private final ApplicationEventPublisher publisher;

    public void foo() {
        publisher.publishEvent(new SomeEvent(this));
    }
}
package org.example;

import org.springframework.context.ApplicationEvent;

public class SomeEvent extends ApplicationEvent {
    public SomeEvent(Object source) {
        super(source);
    }
}

这些是 spock 测试:

package org.example

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.boot.test.web.server.LocalServerPort
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.test.context.event.ApplicationEvents
import org.springframework.test.context.event.RecordApplicationEvents
import spock.lang.Specification

@RecordApplicationEvents
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SomeControllerTest extends Specification {
    @Autowired
    ApplicationEvents events;

    @LocalServerPort
    int port

    TestRestTemplate restTemplate = new TestRestTemplate()

    def "calling / fires an event"() {
        given:
        String url = sprintf("http://localhost:${port}/")

        when:
        ResponseEntity<Void> response = restTemplate.postForEntity(url, null, Void.class)

        then:
        response.statusCode == HttpStatus.OK

        and:
        events.stream(SomeEvent.class).count() == 1
    }
}
package org.example

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.event.ApplicationEvents
import org.springframework.test.context.event.RecordApplicationEvents
import spock.lang.Specification

@RecordApplicationEvents
@SpringBootTest
class SomeServiceTest extends Specification {
    @Autowired
    ApplicationEvents events;

    @Autowired
    SomeService uut;

    def "some service fires some event"() {
        when:
        uut.foo()

        then:
        events.stream(SomeEvent.class).count() == 1
    }
}

这是测试失败:

Condition not satisfied:

events.stream(SomeEvent.class).count() == 1
|      |                |      |       |
|      |                |      0       false
|      |                class org.example.SomeEvent
|      <java.util.stream.ReferencePipeline$3@644e6a8e val$mapper=inaccessible this$0=inaccessible sourceStage=inaccessible previousStage=inaccessible sourceOrOpFlags=inaccessible nextStage=inaccessible depth=inaccessible combinedFlags=inaccessible sourceSpliterator=inaccessible sourceSupplier=inaccessible linkedOrConsumed=inaccessible sourceAnyStateful=inaccessible sourceCloseAction=inaccessible parallel=inaccessible>
Current ApplicationEvents

    at org.example.SomeControllerTest.calling / fires an event(SomeControllerTest.groovy:35)
Java spring-boot events groovy spock

评论


答: 暂无答案