FlexUnit component testing patterns: use addAsync or manually initialize? - apache-flex

We've been using Flex for about 6 months here at work, and I found that my first batches of FlexUnit tests involving custom components would tend to follow this sort of pattern:
import mx.core.Application;
import mx.events.FlexEvent;
import flexunit.framework.TestCase;
public class CustomComponentTest extends TestCase {
private var component:CustomComponent;
public function testSomeAspect() : void {
component = new CustomComponent();
// set some properties...
component.addEventListener(FlexEvent.CREATION_COMPLETE,
addAsync(verifySomeAspect, 5000));
component.height = 0;
component.width = 0;
Application.application.addChild(component);
}
public function verifySomeAspect(event:FlexEvent) : void {
// Assert some things about component...
}
override public function tearDown() : void {
try {
if (component) {
Application.application.removeChild(component);
component = null;
}
} catch (e:Error) {
// ok to ignore
}
}
Basically, you need to make sure the component has been fully initialized before you can reliably verify anything about it, and in Flex this happens asynchronously after it has been added to the display list. So you need to setup a callback (using FlexUnit's addAsync function) to be notified when that's happened.
Lately i've been just manually calling the methods that the runtime would call for you in the necessary places, so now my tests tend to look more like this:
import flexunit.framework.TestCase;
public class CustomComponentTest extends TestCase {
public function testSomeAspect() : void {
var component:CustomComponent = new CustomComponent();
component.initialize();
// set some properties...
component.validateProperties();
// Assert some things about component...
}
This is much easier to follow, but it kinda feels like I'm cheating a little either way. The first case is slamming it into the current Application (which would be the unit test runner shell app), and the latter isn't a "real" environment.
I was wondering how other people would handle this sort of situation?

I see nothing wrong with using the async version. I can agree that the second version is shorter, but I'm not sure that I think it's easier to follow. The test does a lot of things that you wouldn't normally do, whereas the first example is more true to how you would use the component outside the test environment.
Also, in the second form you have to make sure that you do exactly what the framework would do, miss one step and your test isn't relevant, and each test must repeat this code. Seems to me it's better to test it in a situation that is as close to the real thing as possible.
You could have a look at dpUint's sequences, they made component testing a little more declarative:
public function testLogin():void {
var passThroughData:Object = new Object();
passThroughData.username = "myuser1";
passThroughData.password = "somepsswd";
var sequence:SequenceRunner = new SequenceRunner(this);
sequence.addStep(new SequenceSetter(form.usernameTI, {text:passThroughData.username}));
sequence.addStep(new SequenceWaiter(form.usernameTI, FlexEvent.VALUE_COMMIT, 100));
sequence.addStep(new SequenceSetter(form.passwordTI, {text:passThroughData.password}));
sequence.addStep(new SequenceWaiter(form.passwordTI, FlexEvent.VALUE_COMMIT, 100));
sequence.addStep(new SequenceEventDispatcher(form.loginBtn, new MouseEvent("click", true, false)));
sequence.addStep(new SequenceWaiter(form, "loginRequested", 100));
sequence.addAssertHandler(handleLoginEvent, passThroughData);
sequence.run();
}
(example from the dpUint wiki, see here for more info).

Related

"Add" appears to be working in WebFlux, but seems like there must be a "more accepted way"

New to WebFlux, reactive, and handlers.
I am able to get a Mono<> from a ServerRequest and process the contained POJO to add a new tuple to a database. But, it seems like there should be a "better" or "more accepted" way to write this code.
Any help/input with the code in AccountRequestHandler would be appreciated, especially with explanations of the rationale behind the recommend change(s).
Router implementation (stripped down to only "POST")...
#Configuration
public class AccountRequestRouter {
#Bean
public RouterFunction<ServerResponse> route(AccountRequestHandler requestHandler) {
return nest(path("/v2"),
nest(accept(APPLICATION_JSON),
.andRoute(RequestPredicates.POST("/accounts"), requestHandler::addAccount)
));
}
}
Handler implementation...
The code where I'm actually doing the add, and then separately creating a ServerResponse, is what I'm focused on. It seems "clunky", especially since AccountService.addAccount() returns a Mono on completion.
#Component
public class AccountRequestHandler {
#Autowired
private mil.navy.ccop.service.accounts.account.AccountService accountService;
public Mono<ServerResponse> addAccount(ServerRequest request) {
return request.bodyToMono(Account.class).flatMap(account -> {
accountService.addAccount(account);
return ServerResponse.ok().build();
})
.switchIfEmpty(ServerResponse.badRequest()
.contentType(APPLICATION_JSON)
.build(Mono.empty()));
}
}
AccountService implementation (again, stripped down)...
#Service
class AccountService {
#Autowired
private AccountRepository accounts;
public AccountService() {
}
public Mono<Void> addAccount(Account account) {
Account proxy;
// make sure that accountId is set to support auto-generation of synthetic key value
proxy = new Account(-1, account.getShortName(), account.getLongName(), account.getDescription());
accounts.save(proxy);
return Mono.empty();
}
}
Appreciating all the help in ramping up on this style of programming....
well first of all, you have 2 addAccount, that can be a bit confusing.
Second of all, what kind of "repository" are you writing too? if its an sql repo you need to properly wrap it in a Mono.fromCallable() otherwise it will block the Reactive thread pool and you can have really bad performance.
Yes there are other ways of doing things. A lot of people tend to do things in flatmap or map and sure it is completely possible to do things here, but for the semantics i'd say it is less good.
map and flatmap are usually used to perform some sort of computation on the inner value of the mono and then return the same or a new value and or type inside the mono.
i would rewrite this like such.
return void here:
public void addAccount(Account account) {
Account proxy;
// make sure that accountId is set to support auto-generation of synthetic key value
proxy = new Account(-1, account.getShortName(), account.getLongName(), account.getDescription());
accounts.save(proxy);
}
And here:
public Mono<ServerResponse> addAccount(ServerRequest request) {
return request.bodyToMono(Account.class)
.doOnSuccess(account -> {
accountService.addAccount(account);
}).then(ServerResponse.ok().build())
.switchIfEmpty(ServerResponse.badRequest()
.contentType(APPLICATION_JSON)
.build());
}
there are a number of different doOn methods that are ment to be used to consume and do "side effects" on things. Like doOnSuccess, doOnError, doOnCancel etc. etc.
you also have then and thenReturn which will just return whatever you put in them. Then returns whatever Mono you put in it. thenReturn wraps whatever value you put into it into a Mono and returns it.

How to get different singleton in different module that create the same singleton in Flex?

I had study 「Beware of singleton in Flex modules」
in http://www.devahead.com/blog/2010/03/beware-of-singleton-in-flex-modules/
and a lot of information tell me that different module with different content,but in my case it doesn't work!
why the different module use the same static object?
I'm trying to use module wide singleton,but it work like application wide singleton.
Can someone help me how to make module wide singleton.
the short code is like:
<s:Application>
<s:ModuleLoader id="A" creationComplete="loadAModule()"/>
<s:ModuleLoader id="B" creationComplete="loadBModule()"/>
</s:Application>
//-----------AModule
<s:Module>
var aITx:ITx=Tx.newInstant();//Tx extend ITX
tracc(aITx.instantId);
...
</s:Module>
//-----------BModule
<s:Module>
var aITx:ITx=Tx.getInstance();//Tx extend ITX
tracc(aITx.instanceID);
...
</s:Module>
//-----singleton class
public class Tx extends EventDispatcher implements ITx
{
public function Tx()
{
// Add listeners
addEventListeners();
}
private static var instance:Tx;
public static function getInstance():Tx
{
if (!instance)
{
instance = new Tx();
// Generate a random instance ID
instance._instanceID = Math.round(Math.random() * 100);
trace("create new itx id="+instance.instanceID);
}else{
trace("use old itx id="+instance.instanceID);
}
return instance;
}
protected var _instanceID: Number = NaN;
public function get instanceID(): Number
{
return _instanceID;
}
}
I think your problem is related to the context the modules are loaded in. In your case I guess all of your modules are loaded into the same context. In one context there is only one version of one class. Therefore there is only one instance of your Singleton. If you want to have separate classes, you have to load each module into its own context. Have a look at this link which explains the context stuff pretty good: http://livedocs.adobe.com/flex/3/html/help.html?content=05_Display_Programming_33.html

Verify method calls on items in a collection with Moq

My problem is NOT trying to simply verify whether a method was called or not. Instead, I have a method that works on a collection of objects and I want to verify that a method on all of the collection items is being called.
Use the example of a plug-in model where I have a plug-in manager that contains a collection of plug-in objects. Each plug-in subclasses the PlugIn abstract base class which exposes an abstract Initialize method. In my test I want to make sure that Initialize is called on every plug-in regardless of whether one of them throws an exception (just part of a larger test suite).
My initial approach was to create a collection of mocked plug-ins, then configure the class under test (PlugInManager) to use the mocked objects. I then perform the test by calling PlugInManager.DoWork() which should iterate through the collection, calling DoWork() on each item.
The full test codes is as follows:
[TestMethod()]
public void MyTest()
{
// ARRANGE
var testParameter = new Something();
var mockPlugIns = new Collection<Mock<PlugIn>>()
{
new Mock<PlugIn>(),
new Mock<PlugIn>(),
new Mock<PlugIn>()
};
var plugIns = new Collection<PlugIn>();
foreach (var plugIn in mockPlugIns)
plugIns.Add(plugIn.Object);
var testManager = new PlugInManager()
{
PlugIns = plugIns
};
// ACT
testManager.DoWork(testParameter);
// ASSERT
foreach (var mockPlugIn in mockPlugIns)
mockPlugIn.Verify(plugin => plugin.DoWork(testParameter), Times.Once());
// Also tried using It.IsAny<Something>()
}
public abstract class PlugIn
{
abstract void DoWork(Something something);
}
public sealed class PlugInManager
{
public IEnumerable<PlugIn> PlugIns { get; set; }
public void DoWork(Something something)
{
foreach (var plugIn in PlugIns)
plugIn.DoWork(something);
}
}
Unfortunately, Verify fails for every item.
I've stepped through the code and see that it actually is working correctly and the Initialize method is being called on every item. When, then, is Verify failing???
UPDATE #1
I've updated the post to show the entire test method in one block. I've also changed the method to require a parameter as is the case in my real code (now).
UPDATE #2
The error I receive when running the test is:
Moq.MockException:
Expected invocation on the mock once, but was 0 times: plugin => plugin.DoWork(It.IsAny<Something>())
No setups configured.
No invocations performed.
As mentioned, when I step through the unit test I see that each of the plugins are actually being called. For some reason, however, Moq doesn't seem to be registering it or recognizing it.
UPDATE #3
After playing with the test code more, I discovered that I could make the test pass with a simple change. The test passes if I replace the foreach loop in the middle of the method with the following:
plugIns.Add(mockPlugIns[0]);
plugIns.Add(mockPlugIns[1]);
plugIns.Add(mockPlugIns[2]);
I don't see how this is making a difference and would ultimately like to make the number of items dynamic so the tests aren't always testing the case when there are three, so using the foreach is really what I need.
Any ideas?
This is actually not true and upon further testing this morning, I find that everything is working fine with the original foreach loop. I have no idea what changed but I tried many different variations late last night and while the code I have this morning looks just like what is posted, for whatever reason, the test is now passing!?!?!?!?
This worked for me in LINQPad with Moq 4. The only thing I changed was adding the parentheses on Times.Once().
void Main()
{
var MockPlugIns = new Collection<Mock<PlugIn>>()
{
new Mock<PlugIn>(),
new Mock<PlugIn>(),
new Mock<PlugIn>()
};
var plugIns = new Collection<PlugIn>();
foreach (var mockPlugIn in MockPlugIns)
plugIns.Add(mockPlugIn.Object);
var testManager = new PlugInManager()
{
PlugIns = plugIns
};
testManager.Initialize();
foreach (var mockPlugIn in MockPlugIns)
mockPlugIn.Verify(plugin => plugin.Initialize(), Times.Once());
}
public abstract class PlugIn
{
public abstract void Initialize();
}
public class PlugInManager
{
public void Initialize()
{
foreach (var plugIn in PlugIns)
{
plugIn.Initialize();
}
}
public Collection<PlugIn> PlugIns { get; set; }
}
UPDATE
I ran your updated test code, and it passed given the following implementation:
public class PlugInManager
{
public void DoWork(Something s)
{
foreach (var plugIn in PlugIns)
{
plugIn.DoWork(s);
}
}
public Collection<PlugIn> PlugIns { get; set; }
}
It passed with or without the It.IsAny change you mentioned. One initial thought was that you might not have been passing the same instance of Something to the plug-ins, but It.IsAny would have resolved that.
In short, it appears that you are doing everything right in the tests. Perhaps the issue is in the actual implementation.
Please post your implementation of PlugInManager.DoWork and the exact error message you get when the test fails. Also, what version of Moq are you using?
UPDATE
I cut-and-pasted your code and tried it. I had to make one change: abstract void DoWork on abstract class PlugIn needs to be public. After making that change it compiles and the test passes. If I comment out the "ACT" portion of your test, it fails with the error message you saw (as I would expect).
Something is different in your project or environment. I'm running .NET 4 (not Mono) under Windows 64 with Moq 4.0. Everything you have posted is correct. I would suggest confirming that you're running the latest binary of Moq, checking your project references, and trying some very simple verification tests to insure that Moq is working.

Strange behavior from getDefinitionByName

I've created a class that loads it's subclasses based on a name passed to it. The function uses getDefinitionByName, gets the class type, and instantiates it, and returns it if the class is a subtype of the class that owns this method. The subtypes are all mxml files that extend the base class, in order to simplify instantiating controls.
However, in the case where I pass it a fully qualified name, it works in my unit tests but fails when I execute it in the context of my application. Is there a gotcha in getDefinitionByName that makes it behave differently in different execution contexts? Is there a simpler way to load classes by their qualified name?
static public function loadDisplay(className:String, extendedClassName:String = null):FeatureDisplay
{
try
{
trace("Loading", className);
var cls:Class = getDefinitionByName(className) as Class;
var display:FeatureDisplay = new cls() as FeatureDisplay;
if(display)
{
return display;
}
else
{
trace(className, "is not a subclass of FeatureDisplay");
return null;
}
}
catch(error:Error)
{
trace("Error loading", className);
trace("Error:", error.message);
}
return null;
}
My first question is are you explicitly using any of the classes anywhere? If you do not actually use a class, even if it is imported, ActionScript may not end up keeping a copy of the class's definition in the swf.
That said, you're better off avoiding getDefinitionByName, describeType, getQualifiedClassName or getQualifiedSuperclassName if you can possibly avoid them. They are memory hogs and it is generally best to avoid them. (unless you do not have control over which classes will be used at run time and they HAVE to be used through getDefinitionByName).
My suggestion is that you replace getQualifiedClassName with a swtich...case:
// Import the subclasses.
import path.to.SpriteFeatureDisplay;
import path.to.OtherFeatureDisplay;
class FeatureDisplay extends Sprite{
//Make one public static const per class.
public static const SPRITE_FEATURE_DISPLAY:String = "sprite_feature_display";
public static const OTHER_FEATURE_DISPLAY:String = "other_feature_display";
public static function loadDisplay( className:String,
extName:String = null ):FeatureDisplay
{
trace("Loading", className);
// This will ensure that each of the classes is stored in the swf
// it will behave faster, and it is less prone to errors (note that
// try...catch is not needed).
swtich( className )
{
case SPRITE_FEATURE_DISPLAY:
return new SpriteFeatureDisplay();
case OTHER_FEATURE_DISPLAY:
return new OtherFeatureDisplay();
default:
trace( "Requested class " + className + " could not be created..." +
"\nPlease make sure that it is a subclass of FeatureDisplay" );
return null;
}
return null;
}
}
FYI, I've seen the following method of keeping classes used in Flex's source code:
// References.cs
// notice the double reference: one to import, the other to reference
import package.to.ClassA; ClassA;
import package.to.ClassB; ClassB;
import package.to.ClassC; ClassC;
Of course, you still have to reference the "References" class somewhere.

Flex, Flexunit: How to test that an event is dispatched twice?

I'm testing some event dispatch code in a Flex app, using FlexUnit's addAsync method for testing that events are dispatched. Great so far, I can ensure that at least one event was fired. However, I want to be a bit more detailed; I want to ensure that exactly the set of events I'm expecting are dispatched. Is there a useful test pattern (or, even, different test framework -- I'm flexible!) to accomplish this?
I tried this code, but it doesn't seem to get invoked the second time:
protected function expectResultPropertyChange(event: Event, numberOfEvents: int = 1): void {
trace("Got event " + event + " on " + event.target + " with " + numberOfEvents + " traces left...");
assertTrue(event.type == ResponseChangedEvent.RESPONSE_CHANGED);
if (numberOfEvents > 1) {
event.target.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, addAsync(expectResultPropertyChange, 1000, numberOfEvents - 1));
}
}
public function testSomething(): void {
requiredQuestion.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, addAsync(expectResultPropertyChange, 1000, 2));
requiredQuestion.responseSelected("1", true);
requiredQuestion.responseSelected("2", true);
}
In response to the comment...
What if the event is dispatched
directly? responseSelected doesn't
trigger an asynchronous event on a
composite object, it simply dispatched
the RESPONSE_CHANGED event itself
directly. I'm not seeing how this
approach can be mocked using your
method. Mind you, I'm fuzzy on the
mock testing practice as-is, so I'm
probably missing a simple solution
here.
..in that case you don't need to use a mock or addAsync. Something like this will do:
public function testSomething(): void
{
var requiredQuestion : RequiredQuestion = new RequiredQuestion();
var callCount : int = 0;
requiredQuestion.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, function(event : ResponseChangedEvent)
{
callCount++;
});
requiredQuestion.responseSelected("1", true);
requiredQuestion.responseSelected("2", true);
assertEquals(2, callCount);
}
This is going to be a high level example of how a similar problem could be solved using a mocked out object of whatever it is that's doing the asynchronous call. Obviously i can't see your code so i can't give you a precise example.
So, as i said in the comment, you can mock out a dependency in a class to fake asynchronous calls so that they become synchronous. Take the below class
public class RequiredQuestion extends EventDispatcher
{
private var someAsynchronousObject : IAsynchronousObject;
public function RequiredQuestion(someAsynchronousObject : IAsynchronousObject = null)
{
someAsynchronousObject = someAsynchronousObject || new AsynchronousObject();
someAsynchronousObject.addEventListener(Event.COMPLETE, asyncCallComplete);
}
public function responseSelected(id : String, flag : Boolean) : void
{
//Will asynchronously fire the Event.COMPLETE event
someAsynchronousObject.startAsynchrounsCall();
}
protected function asyncCallComplete(event : Event) : void
{
dispatchEvent(new ResponseChangedEvent(ResponseChangedEvent.RESPONSE_CHANGED));
}
}
So by default you are using the concrete class that you want to use unless someAsynchronousObjec is injected into the class via the constructor. AsycnhronousObject probably has it's own unit tests or it's in an external class so you don't really want, or need to be testing its functionality. What you can now do is create a mock object that implements IAsynchronousObject that can be used to fake its behavior. Using the ASMock framework the test could look something like this:
public function testSomething(): void
{
var mockIAsycnhronousObject : IAsynchronousObject =
IAsynchronousObject(mockRepository.createStrict( IAsynchronousObject));
SetupResult.forEventDispatcher(mockIAsycnhronousObject);
SetupResult.forCall(mockIAsycnhronousObject.startAsynchronousCall())
.dispatchEvent(new Event(Event.COMPLETE)); // all calls to the startAsynchronousCall method and dispatch the complete event everytime it's called.
mockRepository.replayAll();
var requiredQuestion : RequiredQuestion = new RequiredQuestion(mockIAsycnhronousObject);
var callCount : int = 0;
requiredQuestion.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, function(event : ResponseChangedEvent)
{
callCount++;
});
requiredQuestion.responseSelected("1", true);
requiredQuestion.responseSelected("2", true);
assertEquals(2, callCount);
mockRepository.verifyAll();
}
This is just one example of how mocking can help you unit tests. There's a whole wealth of info out there on mocking although it is still very new to ActionScript (released in December). ASMock is based on the .net Rhino mocks so searching for Rhino mocks should throw up a lot more results if you need help.
Definitely a different way of thinking but once you get into it you tend to wonder how you got by in unit testing without them.

Resources