提问人:Sören 提问时间:10/12/2023 最后编辑:Sören 更新时间:10/12/2023 访问量:42
ApplicationEvents 声称通过 TestRestTemplate 调用时未触发我的事件
ApplicationEvents claims my event wasn't fired, when called via TestRestTemplate
问:
我有一个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)
答: 暂无答案
评论