【发布时间】:2019-04-25 18:37:02
【问题描述】:
我正在尝试对标有 websocket 范围的简单组件进行简单测试。问题是我收到此错误:
Scope 'websocket' is not active for the current thread;
这很有意义,因为我使用模拟的 WebSocket 客户端执行登录,并且在 Spring 应用程序的客户端上下文中,客户端创建的 websocket 会话没有影响。
测试 websocket 范围组件的正确方法是什么?
组件类:
@Service
@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class TrackerService {
private final ConcurrentMap<String, Collection<Geolocation>> vehicleBeingTracked = new ConcurrentHashMap<>();
public void startTracking(String plateSequence) {
vehiclesBeingTracked.put(plateSequence, new ArrayList<>());
}
public void stopTracking(String plateSequence) {
vehiclesBeingTracked.remove(plateSequence);
}
public void spotVehicle(String plateSequence, Geolocation geo) {
vehiclesBeingTracked.get(plateSequence).add(geo);
}
public boolean isBeingTracked(String plateSequence) {
return vehiclesBeingTracked.containsKey(plateSequence);
}
}
控制器类:
@Controller
@MessageMapping("/operational/tracker")
public class TrackerController {
@Autowired
private TrackerService trackerService;
@MessageMapping("/plate/{plateSequence}/track.start")
public void startTracking(@DestinationVariable("plateSequence") String plateSequence) {
trackerService.startTracking(plateSequence);
}
}
测试类:
@RunWith(SpringRunner.class)
@ContextConfiguration
@SpringBootTest(classes = UnifyApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ActiveProfiles("test")
public class TrackerTest {
@Autowired
private TrackerService trackerService;
@Test
public void startTracking() {
TrackerClient client = new TrackerClient("ws://localhost:9050/operational/websocket", "admin", "admin");
client.connectAndWait();
client.send("/operational/tracker/plate/ABC1234/track.start");
TimeUnit.SECONDS.sleep(1);
boolean result = trackerService.isBeingTracked("ABC1234"); // Here is the error
Assert.assertTrue(result);
}
}
【问题讨论】:
-
请给我们看一下你的代码。您是否创建了使用 AbstractWebSocketMessageBrokerConfigurer 扩展配置的 websocket?您使用的是哪个客户端?如果您使用 stomp,则有一个名为 WebSocketStompClient 的内置客户端
-
是的,实际上系统运行良好。我使用的是单例范围和一些静态引用。现在我正在重构代码以使用 websocket 范围,但我被困在这种测试上。
-
当然它会失败,因为测试不在网络套接字范围内运行。它只能从您的测试用例不是的活动 Web 套接字连接内部获得。所以你需要找到一种不同的测试方式。您可能想要使用模拟而不是实际的作用域对象,而不是
@Autowired使用@MockBean。 -
但是无论如何都需要测试 websocket 范围的服务。那么,怎么可能做到呢?有没有办法在测试线程中获取会话上下文?
标签: java spring spring-boot spring-test spring-websocket