试验触发器标识符Satna。即使如此,采用恰当的开发工具仍然可以同时实现单纯性和可移植性。
许多 Spring Boot Web 插件要求您胜过一般来说的 REST 西北侧并开始拒绝接受 WebSocket 相连。与此同时,单纯的 JUnit 试验已经落伍,突然间每一人都在谈及Spock的发展潜力。
所有那些变化听起来令人激动,您想试著这种新奇的方式。不过,假如应用领域失当,那些技术可能会得不偿失,导致试验不稳定且无法增容——这是触发器操作方式的一般来说付出。那么,怎样防治呢?继续写作以介绍除非您介绍怎样特别针对常用的嫌犯(比如市场竞争条件和误用),您的 WebSocket 覆盖面是何等难和令人信服。为的是使那个过程更加成功,请亦须协助扩充其中两个协助流程类,比如TextWebSocketHandler。为的是深入研究确保安全,他们将同时实现RFC 862:科洛涅县协定。须要特别注意的是,他们将忽视空消息,以使服务项目试验更有意思。这是这样两个执行流程的模样:public class EchoSocket extends TextWebSocketHandler {@Override public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException { if (message.getPayload().isEmpty()) return; session.sendMessage(message);}}然后,您须要两个WebSocketConfigurer同时实现来在某一门牌号下注册登记您的执行流程 bean。下面的执行流程被新闻稿为 bean 并附带到/echo:@Configuration@EnableWebSocketpublic class SocketConfig implements WebSocketConfigurer {@Override public void registerWebSocketHandlers( WebSocketHandlerRegistry registry){ registry.addHandler(echo(),”/echo”);} @Bean public EchoSocket echo(){ return new EchoSocket();}}有了这两个类,插件应该在locet 相连的单纯方式,因此他们须要两个应用领域流程库:
com.neovisionariesnv-websocket-client2.8
首先要校正的是相连是否被拒绝接受。假如他们让 Spring 选择两个乱数路由器来开启,他们须要知道那个值——所以他们用@LocalServerPort转化成它。这时,请读懂强制性立刻接上他们在每一试验中采用的套传输层。不然,随着试验数量和复杂程度的增加,以意料之外的方式阻碍的未停用套接字的数量也会增加:首先要校正的是相连是否被拒绝接受。假如他们让 Spring 选择两个乱数路由器来开启,他们须要知道那个值——所以他们用@LocalServerPort转化成它。这时,请读懂强制性立刻接上他们在每一试验中采用的套传输层。不然,随着试验数量和复杂程度的增加,以意料之外的方式阻碍的未停用套传输层的数量也会增加:@SpringBootTest( classes = SpringWsApplication.class, webEnvironment = RANDOMPORT)class EchoSocketTest extends Specification {@LocalServerPort int port def “socket opens”(){ when: def socket = new WebSocketFactory().createSocket(“http://localhost:$/echo”).connect() then: socket.isOpen() cleanup: socket.disconnect(WebSocketCloseCode.NORMAL, null,0)}}到目前为止一切成功,试验通过,所以他们知道他们可以打开和停用套传输层。当他们开始发送和接收消息时,问题就变得不那么明显了。与普通的 HTTP 调用不同,WebSocket 通信不是以请求-响应的方式进行的。当文本消息发送到套传输层时,您不应该期望同步响应。Spock 基于交互的试验:Mocks 来了在他们继续之前,让他们看一下将在本文其余部分采用的两种方式:
def openSocket(){ new WebSocketFactory().createSocket(“http://localhost:$/echo”).connect()}static def closeSocket(socket){ socket.disconnect(WebSocketCloseCode.NORMAL, null,0)}
考虑到他们已经知道并查看应用领域流程库中的 WebSocket 类,提交文本消息似乎很容易—— sendText(String message)。不过,他们仍然须要找到一种接收响应的方式。没有receive()方式,因此必须注册登记两个WebSocketListener。他们怎样校正监听器是否被调用?Spock 文档有一整节关于基于交互的试验,他们的意思是采用模拟:
def “responds with original message”(){ given: def socket = openSocket() and: def listenerMock = Mock(WebSocketListener) socket.addListener(listenerMock) when: socket.sendText(“Hello”) then:1 * listenerMock.onTextMessage(,”Hello”) cleanup: closeSocket(socket)}
因此,他们创建了两个模拟,将其添加为套传输层侦听器,提交一条文本消息,并期望模拟只被调用一次,因为这就是Echo 协定的工作方式。然后,他们试著运行试验,令人惊讶的是它失败了:Too few invocations for:1* listenerMock.onTextMessage(,”Hello”)(0 invocations)Unmatched invocations (ordered by similarity):None
是等待EchoSocket接收消息并响应。太好了——他们得到了两个比赛条件。假如你在断言之前添加两个简短的sleep(),它可能会通过——但是你做错了两件事:您使试验运行的时间超出了必要的时间;即,100毫秒很可能比它须要的多。您不能确定100毫秒总是足够的——每10次或1000次执行仍然可能失败,您和您的团队须要介绍这是该试验的本质。就此而言,假如您遵循这条路径,那么您的所有 WebSocket 试验都是一样的。BlockingVariable:对抗市场竞争条件的终极武器下面提到的问题和原则证明了对同步机制的须要。一种将执行试验的线程与在响应到达后调用他们的WebSocketListener的线程进行协调。Spock 提供了两个名为BlockingVariable的构造,在他们的文档中没有解释——可能是因为它相当单纯。为的是单纯确保安全,他们可以将此变量描述为给定类型值的包装器。该值的设置与任何其他设置器一样,但在调用get()时它会产生两种不同的结果——它要么立刻返回该值,假如它已被设置,或者等待给定时间设置它并然后失败。您可以考虑通过以下方式采用BlockingVariable :采用预期什么,假如它从未到达- 对 get()的调用有权使试验失败。
def “responds with original message”(){ given: def latch = new BlockingVariable(0.5) and: def socket = openSocket() socket.addListener(new WebSocketAdapter(){ @Override void onTextMessage(WebSocket websocket, String text){ latch.set(text)} }) when: socket.sendText(“Hello”) then: with(latch.get()){ it ==”Hello”} cleanup: closeSocket(socket)}
应该这样做——不再有市场竞争条件。试验被迫等待接收消息的线程响应。它也须要尽可能多的时间。设置值的那一刻,get()方式返回,所有剩余的断言都被执行。随着您的试验套件的增长,请考虑采用一种实用方式替换下面的 and:块,该方式可以打开两个套传输层并将其一次性转发到两个闩锁。您不希望像下面这样的样板标识符分散您对试验背后的逻辑的特别注意力:
def openSocket(latch){ openSocket().addListener(new WebSocketAdapter(){ @Override void onTextMessage(WebSocket websocket, String text){ latch.set(text)} })}
所以你有它- 有了你的第两个有意义和可靠的试验,你和你的队友没有更多的借口。现在是继续致力于自动化试验覆盖并继续推出所有基于 WebSocket 的惊人功能的时候了!再次,请随意采用GitHub 上提供的源标识符,祝您试验愉快!