View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.messaging.simp.annotation.support;
18  
19  import java.lang.reflect.Method;
20  import java.nio.charset.Charset;
21  import java.security.Principal;
22  
23  import org.junit.Before;
24  import org.junit.Test;
25  import org.mockito.ArgumentCaptor;
26  import org.mockito.Captor;
27  import org.mockito.Mock;
28  import org.mockito.Mockito;
29  import org.mockito.MockitoAnnotations;
30  
31  import org.springframework.core.MethodParameter;
32  import org.springframework.messaging.Message;
33  import org.springframework.messaging.MessageChannel;
34  import org.springframework.messaging.MessageHeaders;
35  import org.springframework.messaging.converter.StringMessageConverter;
36  import org.springframework.messaging.core.MessageSendingOperations;
37  import org.springframework.messaging.handler.annotation.MessageMapping;
38  import org.springframework.messaging.handler.annotation.SendTo;
39  import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
40  import org.springframework.messaging.simp.SimpMessagingTemplate;
41  import org.springframework.messaging.simp.annotation.SubscribeMapping;
42  import org.springframework.messaging.support.MessageBuilder;
43  import org.springframework.messaging.support.MessageHeaderAccessor;
44  import org.springframework.util.MimeType;
45  
46  import static org.junit.Assert.*;
47  import static org.mockito.BDDMockito.*;
48  
49  /**
50   * Test fixture for {@link SubscriptionMethodReturnValueHandler}.
51   *
52   * @author Rossen Stoyanchev
53   */
54  public class SubscriptionMethodReturnValueHandlerTests {
55  
56  	public static final MimeType MIME_TYPE = new MimeType("text", "plain", Charset.forName("UTF-8"));
57  
58  	private static final String PAYLOAD = "payload";
59  
60  
61  	private SubscriptionMethodReturnValueHandler handler;
62  
63  	@Mock private MessageChannel messageChannel;
64  
65  	@Captor ArgumentCaptor<Message<?>> messageCaptor;
66  
67  	private MethodParameter subscribeEventReturnType;
68  
69  	private MethodParameter subscribeEventSendToReturnType;
70  
71  	private MethodParameter messageMappingReturnType;
72  
73  
74  	@Before
75  	public void setup() throws Exception {
76  
77  		MockitoAnnotations.initMocks(this);
78  
79  		SimpMessagingTemplate messagingTemplate = new SimpMessagingTemplate(this.messageChannel);
80  		messagingTemplate.setMessageConverter(new StringMessageConverter());
81  
82  		this.handler = new SubscriptionMethodReturnValueHandler(messagingTemplate);
83  
84  		Method method = this.getClass().getDeclaredMethod("getData");
85  		this.subscribeEventReturnType = new MethodParameter(method, -1);
86  
87  		method = this.getClass().getDeclaredMethod("getDataAndSendTo");
88  		this.subscribeEventSendToReturnType = new MethodParameter(method, -1);
89  
90  		method = this.getClass().getDeclaredMethod("handle");
91  		this.messageMappingReturnType = new MethodParameter(method, -1);
92  	}
93  
94  
95  	@Test
96  	public void supportsReturnType() throws Exception {
97  		assertTrue(this.handler.supportsReturnType(this.subscribeEventReturnType));
98  		assertFalse(this.handler.supportsReturnType(this.subscribeEventSendToReturnType));
99  		assertFalse(this.handler.supportsReturnType(this.messageMappingReturnType));
100 	}
101 
102 	@Test
103 	public void testMessageSentToChannel() throws Exception {
104 
105 		given(this.messageChannel.send(any(Message.class))).willReturn(true);
106 
107 		String sessionId = "sess1";
108 		String subscriptionId = "subs1";
109 		String destination = "/dest";
110 		Message<?> inputMessage = createInputMessage(sessionId, subscriptionId, destination, null);
111 
112 		this.handler.handleReturnValue(PAYLOAD, this.subscribeEventReturnType, inputMessage);
113 
114 		verify(this.messageChannel).send(this.messageCaptor.capture());
115 		assertNotNull(this.messageCaptor.getValue());
116 
117 		Message<?> message = this.messageCaptor.getValue();
118 		SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(message);
119 
120 		assertNull("SimpMessageHeaderAccessor should have disabled id", headerAccessor.getId());
121 		assertNull("SimpMessageHeaderAccessor should have disabled timestamp", headerAccessor.getTimestamp());
122 		assertEquals(sessionId, headerAccessor.getSessionId());
123 		assertEquals(subscriptionId, headerAccessor.getSubscriptionId());
124 		assertEquals(destination, headerAccessor.getDestination());
125 		assertEquals(MIME_TYPE, headerAccessor.getContentType());
126 	}
127 
128 	@Test
129 	@SuppressWarnings({ "unchecked", "rawtypes" })
130 	public void testHeadersPassedToMessagingTemplate() throws Exception {
131 
132 		String sessionId = "sess1";
133 		String subscriptionId = "subs1";
134 		String destination = "/dest";
135 		Message<?> inputMessage = createInputMessage(sessionId, subscriptionId, destination, null);
136 
137 		MessageSendingOperations messagingTemplate = Mockito.mock(MessageSendingOperations.class);
138 		SubscriptionMethodReturnValueHandler handler = new SubscriptionMethodReturnValueHandler(messagingTemplate);
139 
140 		handler.handleReturnValue(PAYLOAD, this.subscribeEventReturnType, inputMessage);
141 
142 		ArgumentCaptor<MessageHeaders> captor = ArgumentCaptor.forClass(MessageHeaders.class);
143 		verify(messagingTemplate).convertAndSend(eq("/dest"), eq(PAYLOAD), captor.capture());
144 
145 		SimpMessageHeaderAccessor headerAccessor =
146 				MessageHeaderAccessor.getAccessor(captor.getValue(), SimpMessageHeaderAccessor.class);
147 
148 		assertNotNull(headerAccessor);
149 		assertTrue(headerAccessor.isMutable());
150 		assertEquals(sessionId, headerAccessor.getSessionId());
151 		assertEquals(subscriptionId, headerAccessor.getSubscriptionId());
152 	}
153 
154 
155 	private Message<?> createInputMessage(String sessId, String subsId, String dest, Principal principal) {
156 		SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create();
157 		headers.setSessionId(sessId);
158 		headers.setSubscriptionId(subsId);
159 		headers.setDestination(dest);
160 		headers.setUser(principal);
161 		return MessageBuilder.withPayload(new byte[0]).copyHeaders(headers.toMap()).build();
162 	}
163 
164 
165 	@SubscribeMapping("/data") // not needed for the tests but here for completeness
166 	private String getData() {
167 		return PAYLOAD;
168 	}
169 
170 	@SubscribeMapping("/data") // not needed for the tests but here for completeness
171 	@SendTo("/sendToDest")
172 	private String getDataAndSendTo() {
173 		return PAYLOAD;
174 	}
175 
176 	@MessageMapping("/handle")	// not needed for the tests but here for completeness
177 	public String handle() {
178 		return PAYLOAD;
179 	}
180 }