I have the following code...
#Controller
#RequestMapping("/stomp/**")
public class StompController {
#MessageMapping("/hello")
#SendTo("/topic/greet")
public Greeting greet(HelloMessage message) throws Exception{
System.out.println("Inside the method "+message.getName());
Thread.sleep(3000);
return new Greeting("Hello, "+message.getName()+"!");
}
}
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/stomp/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stomp/hello").withSockJS();
}
}
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
document.getElementById('response').innerHTML = '';
}
function connect() {
var socket = new SockJS('/stomp/hello');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/stomp/topic/greet', function(greeting){
showGreeting(JSON.parse(greeting.body).content);
});
});
}
function disconnect() {
stompClient.disconnect();
setConnected(false);
console.log("Disconnected");
}
function sendName() {
var name = document.getElementById('name').value;
stompClient.send("/stomp/app/hello", {}, JSON.stringify({ 'name': name }));
}
function showGreeting(message) {
var response = document.getElementById('response');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
response.appendChild(p);
}
</script>
The Client side code seems to connect fine but I don't see the console message meaning to me "/stomp/app/hello" is the wrong path. What should the proper path be?
I also tried /app/stomp/hello no dice...
Update
I can remove the #RequestMapping("/stomp/**") and remove the stomp related stuff and it works fine for my simple test, however, I need it to work for a more complex application that will not allow this.
#RequestMapping and #MessageMapping annotations can be used in similar ways, but are totally different.
#MessageMapping can also be used at the type level (see reference documentation), so you could annotate your controller with #MessageMapping("/stomp/**").
Nothing prevents you from annotating a Controller with both #MessageMapping and #RequestMapping - similar programming model, different purposes.
Related
I created a test source which should send a message to the client every x time. This is the ApiController:
public class TestSourceController : ApiController
{
private static readonly ConcurrentQueue<StreamWriter> ConnectedClients = new ConcurrentQueue<StreamWriter>();
[AllowAnonymous]
[Route("api/sources/test")]
public HttpResponseMessage Get()
{
var response = Request.CreateResponse();
response.Content = new PushStreamContent((Action<Stream, HttpContent, TransportContext>) OnStreamAvailable,
"text/event-stream");
return response;
}
private static void OnStreamAvailable(Stream stream, HttpContent headers, TransportContext context)
{
var clientStream = new StreamWriter(stream);
ConnectedClients.Enqueue(clientStream);
}
private static void DoThings()
{
const string outboundMessage = "Test";
foreach (var clientStream in ConnectedClients)
{
clientStream.WriteLine("data:" + JsonConvert.SerializeObject(outboundMessage));
clientStream.Flush();
}
}
}
The clientStream.Flush(); is called like expected and without exceptions.
I handle it in AngularJS like this:
$scope.handleServerCallback = function (data) {
console.log(data);
$scope.$apply(function() {
$scope.serverData = data;
});
};
$scope.listen = function () {
$scope.eventSource = new window.EventSource("http://localhost:18270/api/sources/test");
$scope.eventSource.onmessage = $scope.handleServerCallback;
$scope.eventSource.onopen = function() { console.log("Opened source"); };
$scope.eventSource.onerror = function (e) { console.error(e); };
};
$scope.listen();
My guess is it's a problem with the server since I can see the "EventStream" from the test call is empty in the chrome debugger.
Does anyone know how to make sure the messages arrive at the client?
The solution was quite easy, according to the spec every line has to end with "\n" and the very last line with "\n\n".
So:
clientStream.WriteLine("data:" + JsonConvert.SerializeObject(outboundMessage) + "\n\n");
Solves it.
Can someone explain to me how to create an instance of this component in a Moq TestMethod? Here is the definition of the class. I need to test the ProcessAutomaticFillRequest method.
public class AutomaticDispenserComponent : IAutomaticDispenserComponent
{
private readonly Lazy<IMessageQueueComponent> _messageQueueComponent;
protected IMessageQueueComponent MessageQueueComponent { get { return _messageQueueComponent.Value; } }
public AutomaticDispenserComponent(Func<IMessageQueueComponent> messageQueueComponentFactory)
{
_messageQueueComponent = new Lazy<IMessageQueueComponent>(messageQueueComponentFactory);
}
public void ProcessAutomaticFillRequest(FillRequestParamDataContract fillRequestParam)
{
if (fillRequestParam.PrescriptionServiceUniqueId == Guid.Empty)
throw new InvalidOperationException("No prescription service was specified for processing fill request.");
if (fillRequestParam.Dispenser == null)
throw new InvalidOperationException("No dispenser was specified for processing fill request.");
var userContext = GlobalContext.CurrentUserContext;
var channel = string.Format(Channel.FillRequest, userContext.TenantId,
userContext.PharmacyUid, fillRequestParam.Dispenser.DeviceAgentUniqueId);
NotificationServer.Publish(channel, fillRequestParam);
}
Here is how I started my test, but I don't know how to create an instance of the component:
[TestMethod]
[ExpectedException(typeof (InvalidOperationException))]
public void FillRequestFailsWhenPrescriptionServiceUniqueIdIsEmpty()
{
// How do I create an instance of automatiqueDispenserComponent here
// since there is Func as constructor parameter?
var fillRequestParam = new FillRequestParamDataContract
{
PrescriptionServiceUniqueId = Guid.Empty
};
_automaticDispensercomponent.ProcessAutomaticFillRequest(fillRequestParam);
// ...
}
Updated the answer based on the comments below. You need to mock the Func parameter for the test.
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void FillRequestFailsWhenPrescriptionServiceUniqueIdIsEmpty()
{
var mockMsgQueueComponent = new Mock<Func<IMessageQueueComponent>>();
var _automaticDispensercomponent = new AutomaticDispenserComponent
(mockMsgQueueComponent.Object);
var fillRequestParam = new FillRequestParamDataContract
{
PrescriptionServiceUniqueId = Guid.Empty
};
_automaticDispensercomponent.ProcessAutomaticFillRequest(fillRequestParam);
}
I'm trying to write this simple test:
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var postProcessingAction = fixture.Freeze<Mock<IPostProcessingAction>>();
var postProcessor = fixture.Freeze<PostProcessor>();
postProcessor.Process("", "");
postProcessingAction.Verify(action => action.Do());
The Verify check fails.
The code for postProcessor.Process is
public void Process(string resultFilePath, string jobId)
{
IPostProcessingAction postProcessingAction =
postProcessingActionReader
.CreatePostProcessingActionFromJobResultXml(resultFilePath);
postProcessingAction.Do();
}
postProcessingActionReader is an interface field initialized through the constructor.
I'm expecting the test to pass but it fails, it turns out the instance of IPostProessingAction returned from the CreatePostProcessingActionFromJobResultXml method is not the same instance as returned from fixture.Freeze<>.
My expectation was that after freezing this Mock object it would inject the underlying mock of the IPostProcessingAction interface in every place its required as well as make all mock methods returning IPostProcessingAction return this same object.
Is my expectation about the return value of the mock methods incorrect?
Is there a way to change this behavior so that mock methods return the same frozen instance?
You need to Freeze the IPostProcessingActionReader component.
The following test will pass:
[Fact]
public void Test()
{
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
var postProcessingActionMock = new Mock<IPostProcessingAction>();
var postProcessingActionReaderMock = fixture
.Freeze<Mock<IPostProcessingActionReader>>();
postProcessingActionReaderMock
.Setup(x => x.CreatePostProcessingActionFromJobResultXml(
It.IsAny<string>()))
.Returns(postProcessingActionMock.Object);
var postProcessor = fixture.CreateAnonymous<PostProcessor>();
postProcessor.Process("", "");
postProcessingActionMock.Verify(action => action.Do());
}
Assuming that the types are defined as:
public interface IPostProcessingAction
{
void Do();
}
public class PostProcessor
{
private readonly IPostProcessingActionReader actionReader;
public PostProcessor(IPostProcessingActionReader actionReader)
{
if (actionReader == null)
throw new ArgumentNullException("actionReader");
this.actionReader = actionReader;
}
public void Process(string resultFilePath, string jobId)
{
IPostProcessingAction postProcessingAction = this.actionReader
.CreatePostProcessingActionFromJobResultXml(resultFilePath);
postProcessingAction.Do();
}
}
public interface IPostProcessingActionReader
{
IPostProcessingAction CreatePostProcessingActionFromJobResultXml(
string resultFilePath);
}
In case you use AutoFixture declaratively with the xUnit.net extension the test could be simplified even further:
[Theory, AutoMoqData]
public void Test(
[Frozen]Mock<IPostProcessingActionReader> readerMock,
Mock<IPostProcessingAction> postProcessingActionMock,
PostProcessor postProcessor)
{
readerMock
.Setup(x => x.CreatePostProcessingActionFromJobResultXml(
It.IsAny<string>()))
.Returns(postProcessingActionMock.Object);
postProcessor.Process("", "");
postProcessingActionMock.Verify(action => action.Do());
}
The AutoMoqDataAttribute is defined as:
internal class AutoMoqDataAttribute : AutoDataAttribute
{
internal AutoMoqDataAttribute()
: base(new Fixture().Customize(new AutoMoqCustomization()))
{
}
}
As of 3.20.0, you can use AutoConfiguredMoqCustomization. This will automatically configure all mocks so that their members' return values are generated by AutoFixture.
In other words, it will auto-configure your postProcessingActionReader to return the frozen postProcessingAction.
Just change this:
var fixture = new Fixture().Customize(new AutoMoqCustomization());
to this:
var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());
"How can i use engine in my console application"
I shouldn't use the ITemplate-interface and Transform-Method.
I am using Tridion 2011
Could anyone please suggest me.
You can't. The Engine class is part of the TOM.NET and that API is explicitly reserved for use in:
Template Building Blocks
Event Handlers
For all other cases (such as console applications) you should use the Core Service.
There are many good questions (and articles on other web sites) already:
https://stackoverflow.com/search?q=%5Btridion%5D+core+service
http://www.google.com/#q=tridion+core+service
If you get stuck along the way, show us the relevant code+configuration you have and what error message your get (or at what step you are stuck) and we'll try to help from there.
From a console application you should use the Core Service. I wrote a small example using the Core Service to search for items in the content manager.
Console.WriteLine("FullTextQuery:");
var fullTextQuery = Console.ReadLine();
if (String.IsNullOrWhiteSpace(fullTextQuery) || fullTextQuery.Equals(":q", StringComparison.OrdinalIgnoreCase))
{
break;
}
Console.WriteLine("SearchIn IdRef:");
var searchInIdRef = Console.ReadLine();
var queryData = new SearchQueryData
{
FullTextQuery = fullTextQuery,
SearchIn = new LinkToIdentifiableObjectData
{
IdRef = searchInIdRef
}
};
var results = coreServiceClient.GetSearchResults(queryData);
results.ToList().ForEach(result => Console.WriteLine("{0} ({1})", result.Title, result.Id));
Add a reference to Tridion.ContentManager.CoreService.Client to your Visual Studio Project.
Code of the Core Service Client Provider:
public interface ICoreServiceProvider
{
CoreServiceClient GetCoreServiceClient();
}
public class CoreServiceDefaultProvider : ICoreServiceProvider
{
private CoreServiceClient _client;
public CoreServiceClient GetCoreServiceClient()
{
return _client ?? (_client = new CoreServiceClient());
}
}
And the client itself:
public class CoreServiceClient : IDisposable
{
public SessionAwareCoreServiceClient ProxyClient;
private const string DefaultEndpointName = "netTcp_2011";
public CoreServiceClient(string endPointName)
{
if(string.IsNullOrWhiteSpace(endPointName))
{
throw new ArgumentNullException("endPointName", "EndPointName is not specified.");
}
ProxyClient = new SessionAwareCoreServiceClient(endPointName);
}
public CoreServiceClient() : this(DefaultEndpointName) { }
public string GetApiVersionNumber()
{
return ProxyClient.GetApiVersion();
}
public IdentifiableObjectData[] GetSearchResults(SearchQueryData filter)
{
return ProxyClient.GetSearchResults(filter);
}
public IdentifiableObjectData Read(string id)
{
return ProxyClient.Read(id, new ReadOptions());
}
public ApplicationData ReadApplicationData(string subjectId, string applicationId)
{
return ProxyClient.ReadApplicationData(subjectId, applicationId);
}
public void Dispose()
{
if (ProxyClient.State == CommunicationState.Faulted)
{
ProxyClient.Abort();
}
else
{
ProxyClient.Close();
}
}
}
When you want to perform CRUD actions through the core service you can implement the following methods in the client:
public IdentifiableObjectData CreateItem(IdentifiableObjectData data)
{
data = ProxyClient.Create(data, new ReadOptions());
return data;
}
public IdentifiableObjectData UpdateItem(IdentifiableObjectData data)
{
data = ProxyClient.Update(data, new ReadOptions());
return data;
}
public IdentifiableObjectData ReadItem(string id)
{
return ProxyClient.Read(id, new ReadOptions());
}
To construct a data object of e.g. a Component you can implement a Component Builder class that implements a create method that does this for you:
public ComponentData Create(string folderUri, string title, string content)
{
var data = new ComponentData()
{
Id = "tcm:0-0-0",
Title = title,
Content = content,
LocationInfo = new LocationInfo()
};
data.LocationInfo.OrganizationalItem = new LinkToOrganizationalItemData
{
IdRef = folderUri
};
using (CoreServiceClient client = provider.GetCoreServiceClient())
{
data = (ComponentData)client.CreateItem(data);
}
return data;
}
Hope this gets you started.
I am mocking a wrapper to an MSMQ. The wrapper simply allows an object instance to be created that directly calls static methods of the MessageQueue class.
I want to test reading the queue to exhaustion. To do this I would like the mocked wrapper to return some good results and throw an exception on the fourth call to the same method. The method accepts no parameters and returns a standard message object.
Can I set up this series of expectations on the method in Moq?
Yup, this is possible if you don't mind jumping through a few minor hoops. I've done this for one of my projects before. Alright here is the basic technique. I just tested it out in Visual Studio 2008, and this works:
var mockMessage1 = new Mock<IMessage>();
var mockMessage2 = new Mock<IMessage>();
var mockMessage3 = new Mock<IMessage>();
var messageQueue = new Queue<IMessage>(new [] { mockMessage1.Object, mockMessage2.Object, mockMessage3.Object });
var mockMsmqWrapper = new Mock<IMsmqWrapper>();
mockMsmqWrapper.Setup(x => x.GetMessage()).Returns(() => messageQueue.Dequeue()).Callback(() =>
{
if (messageQueue.Count == 0)
mockMsmqWrapper.Setup(x => x.GetMessage()).Throws<MyCustomException>();
});
A few notes:
You don't have to return mocked messages, but it's useful if you want to verify expectations on each message as well to see if certain methods were called or properties were set.
The queue idea is not my own, just a tip I got from a blog post.
The reason why I am throwing an exception of MyCustomException is because the Queue class automatically throws a InvalidOperationException. I wanted to make sure that the mocked MsmqWrapper object throws an exception because of Moq and not because of the queue running out of items.
Here's the complete code that works. Keep in mind that this code is ugly in some places, but I just wanted to show you how this could be tested:
public interface IMsmqWrapper
{
IMessage GetMessage();
}
public class MsmqWrapper : IMsmqWrapper
{
public IMessage GetMessage()
{
throw new NotImplementedException();
}
}
public class Processor
{
private IMsmqWrapper _wrapper;
public int MessagesProcessed { get; set; }
public bool ExceptionThrown { get; set; }
public Processor(IMsmqWrapper msmqWrapper)
{
_wrapper = msmqWrapper;
}
public virtual void ProcessMessages()
{
_wrapper.GetMessage();
MessagesProcessed++;
_wrapper.GetMessage();
MessagesProcessed++;
_wrapper.GetMessage();
MessagesProcessed++;
try
{
_wrapper.GetMessage();
}
catch (MyCustomException)
{
ExceptionThrown = true;
}
}
}
[Test]
public void TestMessageQueueGetsExhausted()
{
var mockMessage1 = new Mock<IMessage>();
var mockMessage2 = new Mock<IMessage>();
var mockMessage3 = new Mock<IMessage>();
var messageQueue = new Queue<IMessage>(new [] { mockMessage1.Object, mockMessage2.Object, mockMessage3.Object });
var mockMsmqWrapper = new Mock<IMsmqWrapper>();
mockMsmqWrapper.Setup(x => x.GetMessage()).Returns(() => messageQueue.Dequeue()).Callback(() =>
{
if (messageQueue.Count == 0)
mockMsmqWrapper.Setup(x => x.GetMessage()).Throws<InvalidProgramException>();
});
var processor = new Processor(mockMsmqWrapper.Object);
processor.ProcessMessages();
Assert.That(processor.MessagesProcessed, Is.EqualTo(3));
Assert.That(processor.ExceptionThrown, Is.EqualTo(true));
}