How to get the result of a RemoteObject immediately? - apache-flex

I need to make a function that execute a java method and return his result. It is static becouse a lot of other functions will call this function. So I did this:
public static function FKDescription(dest:String):String{
var jRemote:RemoteObject = new RemoteObject();
var s:String;
jRemote.destination = dest;
jRemote.getValues.addEventListener(ResultEvent.RESULT,valresult);
jRemote.getValues();
function valresult(event:ResultEvent):void{
s = event.result as String;
}
return s;
}
But the function returns null, because the valresult() was not been called at the end of main function. What shoud I do to make FKDescription() return the string that came from remoteobject?
Tanks.

That's because HTTP calls are asynchronous, so you have to way for the result. What you want to do is remove the result handler to it's own function so that it waits for the result, then does something with it. It is NOT possible to do what you're trying to accomplish right now, which is returning the value right away.
Check here on how to do async calls.

as J_A_X said, all the http requests are async, i suggest to refactor your code this way:
public static function FKDescription(dest:String, callback:Function):String{
var jRemote:RemoteObject = new RemoteObject();
var s:String;
jRemote.destination = dest;
jRemote.getValues.addEventListener(ResultEvent.RESULT,valresult);
jRemote.getValues();
function valresult(event:ResultEvent):void{
callback(event.result as String);
}
}
and in the caller, instead of:
ret = FKDescription("something");
otherFunction(ret);
you can do this:
FKDescription("something", otherFunction);

Related

NullReferenceException in unittesting with NUnit, NSubstitute, and async method

I'm doing some unit testing in C# using NUnit and NSubstitute. I have a class called Adapter, which has a method, GetTemplates(), I want to unit test. GetTemplates() uses httpclient, which I have mocked out using an interface.
The call in GetTemplates looks something like:
public async Task<List<Template>> GetTemplates()
{
//Code left out for simplificity.
var response = await _client.GetAsync($"GetTemplates");
if (!response.IsSuccessStatusCode)
{
throw new Exception();
}
}
I want _client.GetAsync to return a HttpResponseMessage with a HttpStatusCode.BadRequest so that I can test if the exception is being thrown.
The test method looks like:
[Test]
public void GetTemplate_ReturnBadRequestHttpMessage_ThrowException()
{
//Arrange.
var httpMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
_client.GetAsync("").Returns(Task.FromResult(httpMessage));
//Act.
var ex = Assert.ThrowsAsync<Exception>(async () => await _Adapter.GetSigningTemplates());
//Assert.
Assert.IsInstanceOf<Exception>(ex);
}
When the method has run, it returns
System.NullReferenceException: Object reference not set to an instance of an object.
What did I do wrong?
That is because the arrangement of the mocked client does not match what is actually invoked when the test is exercised.
The client expects
var response = await _client.GetAsync($"GetTemplates");
but the setup is for
_client.GetAsync("")
note the different arguments passed. When mocks do not get exactly what was setup they usually return the default value of their return type, which in this case is null.
Change the test to use the expected parameter
_client.GetAsync($"GetTemplates").Returns(Task.FromResult(httpMessage));
Reference Return for specific args
or use an argument matcher
_client.GetAsync(Arg.Any<string>()).Returns(Task.FromResult(httpMessage));
Reference Argument matchers

Iterate with asynchronous functions

Using the Twitch API and vert.x - I'm looking to continuously send requests to Twitch's API using a WebClient and Twitch's cursor response to go page by page. However I'm not sure how to go back and keep doing queries until a condition is met due to vert.x's asynchronous nature.
Here's my code so far
public void getEntireStreamList(Handler<AsyncResult<JsonObject>> handler) {
JsonObject data = new JsonObject();
getLiveChannels(100, result -> {
if(result.succeeded()) {
JsonObject json = result.result();
String cursor = json.getJsonObject("pagination").getString("cursor");
data.put("data", json.getJsonArray("data"));
if(json.getJsonArray("data").size() < 100) { // IF NOT LAST PAGE
// GO BACK AND DO AGAIN WITH CURSOR IN REQUEST
}
handler.handle(Future.succeededFuture(data));
} else
handler.handle(Future.failedFuture(result.cause()));
});
}
Ideally I'd be able to call getLiveChannels with the cursor String from the previous request to continue the search.
You will need to use Future composition.
Here's my code for your problem:
public void getEntireStreamList(Handler<AsyncResult<JsonObject>> handler) {
JsonArray data = new JsonArray();
// create initial Future for first function call
Future<JsonObject> initFuture = Future.future();
// complete Future when getLiveChannels completes
// fail on exception
getLiveChannels(100, initFuture.completer());
// Create a callback that returns a Future
// for composition.
final AtomicReference<Function<JsonObject, Future<JsonObject>>> callback = new AtomicReference<>();
// Create Function that calls composition with itself.
// This is similar to recursion.
Function<JsonObject, Future<JsonObject>> cb = new Function<JsonObject, Future<JsonObject>>() {
#Override
public Future<JsonObject> apply(JsonObject json) {
// new Future to return
Future<JsonObject> f = Future.future();
// Do what you wanna do with the data
String cursor = json.getJsonObject("pagination").getString("cursor");
data.addAll(json.getJsonArray("data"));
// IF NOT LAST PAGE
if(json.getJsonArray("data").size() == 100) {
// get more live channels with cursor
getLiveChannels(100, cursor, f.completer());
// return composed Future
return f.compose(this);
}
// Otherwise return completed Future with results.
f.complete(new JsonObject().put("data", data));
return f;
}
};
Future<JsonObject> composite = initFuture.compose(cb);
// Set handler on composite Future (ALL composed futures together)
composite.setHandler(result -> handler.handle(result));
}
The code + comments should speak for themselves if you read the Vert.x docs on sequential Future composition.

Return IQueryable<string>

I'm using pageList (the one made by troy goode), on his example he has
// in this case we return IEnumerable<string>, but in most
// - DB situations you'll want to return IQueryable<string>
private IEnumerable<string> GetStuffFromDatabase()
{
var sampleData = new StreamReader(Server.MapPath("~/App_Data/Names.txt")).ReadToEnd();
return sampleData.Split('\n');
}
Since i'm using a database i changed to IQueryable, but, i don't know what to write inside to return the data from the database, i tried changing the path to ~/App_Data/DatabaseName.sdf but i get that sampleData.Split('\n');
cannot implicitly convert type string to system.linq.iqueryable<string>
How i can change that?
return sampleData.Split('\n').AsQueryable();
The return type of your method is IEnumerable and requires to return as Enumeration
so please do this way
return sampleData.Split('\n').AsEnumerable();

How can I mock an AsyncResponder and the resultant handler functions on a mocked object using FlexUnit 4 and mockolate

I am attempting to write some unit tests for a class I am writing in Flex 4.5.1 using FlexUnit 4 and Mockolate for my testing and mocking framework respectively. I am using as3-signals for my custom events.
The functionality that I am writing and testing is a wrapper class (QueryQueue) around the QueryTask class within the ArcGIS API for Flex. This enables me to easily queue up multiple query tasks for execution. My wrapper, QueryQueue will dispatch a completed event when all the query responses have been processed.
The interface is very simple.
public interface IQueryQueue
{
function get inProgress():Boolean;
function get count():int;
function get completed():ISignal;
function get canceled():ISignal;
function add(query:Query, url:String, token:Object = null):void;
function cancel():void;
function execute():void;
}
Here is an example usage:
public function exampleUsage():void
{
var queryQueue:IQueryQueue = new QueryQueue(new QueryTaskFactory());
queryQueue.completed.add(onCompleted);
queryQueue.canceled.add(onCanceled);
var query1:Query = new Query();
var query2:Query = new Query();
// set query parameters
queryQueue.add(query1, url1);
queryQueue.add(query2, url2);
queryQueue.execute();
}
public function onCompleted(sender:Object, event:QueryQueueCompletedEventArgs)
{
// do stuff with the the processed results
}
public function onCanceled(sender:Object, event:QueryQueueCanceledEventArgs)
{
// handle the canceled event
}
For my tests I am currently mocking the QueryTaskFactory and QueryTask objects. Simple tests such as ensuring that queries are added to the queue relatively straight forward.
[Test(Description="Tests adding valid QueryTasks to the QueryQueue.")]
public function addsQuerys():void
{
var queryTaskFactory:QueryTaskFactory = nice(QueryTaskFactory);
var queryQueue:IQueryQueue = new QueryQueue(queryTaskFactory);
assertThat(queryQueue.inProgress, isFalse());
assertThat(queryQueue.count, equalTo(0));
var query1:Query = new Query();
queryQueue.add(query1, "http://gisinc.com");
assertThat(queryQueue.inProgress, isFalse());
assertThat(queryQueue.count, equalTo(1));
var query2:Query = new Query();
queryQueue.add(query2, "http://gisinc.com");
assertThat(queryQueue.inProgress, isFalse());
assertThat(queryQueue.count, equalTo(2));
var query3:Query = new Query();
queryQueue.add(query3, "http://gisinc.com");
assertThat(queryQueue.inProgress, isFalse());
assertThat(queryQueue.count, equalTo(3));
}
However, I want to be able to test the execute method as well. This method should execute all the queries added to the queue. When all the query results have been processed the completed event is dispatched. The test should ensure that:
execute is called on each query once and only once
inProgress = true while the results have not been processed
inProgress = false when the results have been processed
completed is dispatched when the results have been processed
canceled is never called (for valid queries)
The processing done within the queue correctly processes and packages the query results
So far I can write tests for items 1 through 5 thanks in large part to the answer provided by weltraumpirat. My execute test now currently looks like this.
[Test(async, description="Tests that all queryies in the queue are executed and the completed signal is fired")]
public function executesAllQueriesInQueue():void
{
// Setup test objects and mocks
var query:Query = new Query();
var mockedQueryTask:QueryTask = nice(QueryTask);
var mockedQueryTaskFactory:QueryTaskFactory = nice(QueryTaskFactory);
// Setup expectations
expect(mockedQueryTaskFactory.createQueryTask("http://test.com")).returns(mockedQueryTask);
expect(mockedQueryTask.execute(query, null)).once();
// Setup handlers for expected and not expected signals (events)
var queryQueue:IQueryQueue = new QueryQueue(mockedQueryTaskFactory);
handleSignal(this, queryQueue.completed, verifyOnCompleted, 500, null);
registerFailureSignal(this, queryQueue.canceled);
// Do it
queryQueue.add(query, "http://test.com");
queryQueue.execute();
// Test that things went according to plan
assertThat(queryQueue.inProgress, isTrue());
verify(mockedQueryTask);
verify(mockedQueryTaskFactory);
function verifyOnCompleted(event:SignalAsyncEvent, passThroughData:Object):void
{
assertThat(queryQueue.inProgress, isFalse());
}
}
The QueryQueue.execute method looks like this.
public function execute():void
{
_inProgress = true;
for each(var queryObject:QueryObject in _queryTasks)
{
var queryTask:QueryTask = _queryTaskFactory.createQueryTask(queryObject.url);
var asyncToken:AsyncToken = queryTask.execute(queryObject.query);
var asyncResponder:AsyncResponder = new AsyncResponder(queryTaskResultHandler, queryTaskFaultHandler, queryObject.token);
asyncToken.addResponder(asyncResponder);
}
}
private function queryTaskResultHandler(result:Object, token:Object = null):void
{
// For each result collect the data and stuff it into a result collection
// to be sent via the completed signal when all querytask responses
// have been processed.
}
private function queryTaskFaultHandler(error:FaultEvent, token:Object = null):void
{
// For each error collect the error and stuff it into an error collection
// to be sent via the completed signal when all querytask responses
// have been processed.
}
For test #6 above what I want to be able to do is to test that the data that is returned in the queryTaskResultHandler and the queryTaskFaultHandler is properly processed.
That is, I do not dispatch a completed event until all the query responses have returned, including successful and failed result.
To test this process I think that I need to mock the data coming back in the result and fault handlers for each mocked query task.
So, how do I mock the data passed to a result handler created via an AsyncResponder using FlexUnit and mockolate.
You can mock any object or interface with mockolate. In my experience, it is best to set up a rule and mock like this:
[Rule]
public var rule : MockolateRule = new MockolateRule();
[Mock]
public var task : QueryTask;
Notice that you must instantiate the rule, but not the mock object.
You can then specify your expectations:
[Test]
public function myTest () : void {
mock( task ).method( "execute" ); // expects that the execute method be called
}
You can expect a bunch of things, such as parameters:
var responder:AsyncResponder = new AsyncResponder(resultHandler, faultHandler);
mock( task ).method( "execute" ).args( responder ); // expects a specific argument
Or make the object return specific values:
mock( queue ).method( "execute" ).returns( myReturnValue ); // actually returns the value(!)
Sending events from the mock object is as simple as calling dispatchEvent on it - since you're mocking the original class, it inherits all of its features, including EventDispatcher.
Now for your special case, it would to my mind be best to mock the use of all three external dependencies: Query, QueryTask and AsyncResponder, since it is not their functionality you are testing, but that of your Queue.
Since you are creating these objects within your queue, that makes it hard to mock them. In fact, you shouldn't really create anything directly in any class, unless there are no external dependencies! Instead, pass in a factory (you might want to use a dependency injection framework) for each of the objects you must create - you can then mock that factory in your test case, and have it return mock objects as needed:
public class QueryFactory {
public function createQuery (...args:*) : Query {
var query:Query = new Query();
(...) // use args array to configure query
return query;
}
}
public class AsyncResponderFactory {
public function createResponder( resultHandler:Function, faultHandler:Function ) : AsyncResponder {
return new AsyncResponder(resultHandler, faultHandler);
}
}
public class QueryTaskFactory {
public function createTask (url:String) : QueryTask {
return new QueryTask(url);
}
}
... in Queue:
(...)
public var queryFactory:QueryFactory;
public var responderFactory : AsyncResponderFactory;
public var taskFactory:QueryTaskFactory;
(...)
var query:Query = queryFactory.createQuery ( myArgs );
var responder:AsyncResponder = responderFactory.createResponder (resultHandler, faultHandler);
var task:QueryTask = taskFactory.createTask (url);
task.execute (query, responder);
(...)
...in your Test:
[Rule]
public var rule : MockolateRule = new MockolateRule();
[Mock]
public var queryFactory:QueryFactory;
public var query:Query; // no need to mock this - you are not calling any of its methods in Queue.
[Mock]
public var responderFactory:AsyncResponderFactory;
public var responder:AsyncResponder;
[Mock]
public var taskFactory:QueryTaskFactory;
[Mock]
public var task:QueryTask;
[Test]
public function myTest () : void {
query = new Query();
mock( queryFactory ).method( "createQuery ").args ( (...) ).returns( query ); // specify arguments instead of (...)!
responder = new AsyncResponder ();
mock( responderFactory ).method( "createResponder" ).args( isA(Function) , isA(Function) ).returns( responder ); // this will ensure that the handlers are really functions
queue.responderFactory = responderFactory;
mock( task ).method( "execute" ).args( query, responder );
mock( taskFactory ).method( "createTask" ).args( "http://myurl.com/" ).returns( task );
queue.taskFactory = taskFactory;
queue.doStuff(); // execute whatever the queue should actually do
}
Note that you must declare all mocks as public, and all of the expectations must be added before passing the mock object to its host , otherwise, mockolate cannot configure the proxy objects correctly.

flex3 function not returning String properly

im trying to return a string value from a method inside my script tag however it always returns an object and i cant get at the string value.
Here is the code:
i retrieve the object returned from a webservice call;;
private function getNameResults(e:ResultEvent):String{
var name:Array = new Array(e.result);
var site:String = site_names[0].toString();
Alert.show("site - " +site);
return site;
}
the alert prints out the name fine, however when i try use the value in my next method (which calls the web service which calls getNameResults) i get the object tag
private function getInfo(roomName:String):String{
var site:String =userRequest.getRoomZoneInfo(roomName);
return site;
}
however the value returned here is [object AsyncToken]
any ideas?
You are setting the result of getRoomZoneInfo() to the variable site, but you are casting it as a String. getRoomZoneInfo is returning an object, and because the variable you are sticking it in is a string it is like calling .toString() on the object, which yields the [object AsyncToken].
Basically if getRoomZoneInfo is a webservice call, you cannot get the information you are looking for here, you have to wait until the result comes back and get the string you are looking for there. Make sense?
Your getInfo() method isn't calling getNameResults(). It's calling getRoomZoneInfo(). I don't know what that method does, but I'm guessing it's returning an Object, not a String.
I m getting [ObjectAsyncToken] in variable a instead of string, as I'm retrieving data from database
private function init():void
{
ro.initView();
var a:String=String(ro.getID());
}
database function:
public void initView()
{
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn = DriverManager.getConnection("jdbc:odbc:alarmdsn"," "," ");
Statement s = conn.createStatement();
ResultSet r = s.executeQuery("select * from alarm");
while(r.next()) {
a = r.getString(1);
}
}
catch(Exception e) {}
}
public String getID() {
return a;
}

Resources