Recreating a bunch of components for flex unit testing (flexunit) - actionscript-3

I have a bunch of NumericSteppers (start week, start year, end week, end year), which are deep within ViewStacks, NavigatorContents etc. I wanted to unit test my date steppers, and was wondering how I can go about doing that? When I initialize the top level parent component, the children components don't get created. Do I have to manually add all these components by iterating down the tree (please say no :) )? Can I do it using UIImpersonator?
Sorry if the question is basic, Flex is very new to me.

In Flash, creating unit tests for GUI components is problematic. I generally write unit tests for controllers, presentation models, mediators (etc) -- ie: the non GUI classes that contain business logic.
Writing tests for GUI objects becomes a losing proposition, for many reasons:
the view's logic tends to need to be triggered by user interaction
the view may depend on low level Flash API's (NetStream, Camera, etc) that are difficult to simulate/mock in tests)
running tests that have GUI elements (things that use the stage or that you add to the stage) is not possible when running tests automatically (ie: kicked off by your continuous integration or build system)
tests tend to run slower
I generally avoid writing unit tests for components like a date stepper, which we compose together to form the greater "view". I typically use a presentation model, and if the component has particular business logic that should be tested, the tests are written for the non-gui presentation model class (or controller, or mediator, or whatever).
public class MyViewPM
{
// write a unit test for this method
public function onSubmitButtonClick():void
{
}
}
public class MyView extends Sprite
{
// this is injected by your MVC framework
// or set when the the view is created, or added to stage, etc.
public var pm:MyViewPM;
public function MyView()
{
submitButton.addEventListener(MouseEvent.Click, onMouseClick);
}
private function onMouseClick(event:Event):void
{
pm.onSubmitButtonClick();
}
}

Related

JavaFX FXML Parameter passing from Controller A to B and back

I want to create a controller based JavaFX GUI consisting of multiple controllers.
The task I can't accomplish is to pass parameters from one Scene to another AND back.
Or in other words:
The MainController loads SubController's fxml, passes an object to SubController, switches the scene. There shall not be two open windows.
After it's work is done, the SubController shall then switch the scene back to the MainController and pass some object back.
This is where I fail.
This question is very similar to this one but still unanswered. Passing Parameters JavaFX FXML
It was also mentioned in the comments:
"This work when you pass parameter from first controller to second but how to pass parameter from second to first controller,i mean after first.fxml was loaded.
– Xlint Xms Sep 18 '17 at 23:15"
I used the first approach in the top answer of that thread.
Does anyone have a clue how to achieve this without external libs?
There are numerous ways to do this.
Here is one solution, which passes a Consumer to another controller. The other controller can invoke the consumer to accept the result once it has completed its work. The sample is based on the example code from an answer to the question that you linked.
public Stage showCustomerDialog(Customer customer) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
Stage stage = new Stage(StageStyle.DECORATED);
stage.setScene(
new Scene(
(Pane) loader.load()
)
);
Consumer<CustomerInteractionResult> onComplete = result -> {
// update main screen based upon result.
};
CustomerDialogController controller =
loader.<CustomerDialogController>getController();
controller.initData(customer, onComplete);
stage.show();
return stage;
}
...
class CustomerDialogController() {
#FXML private Label customerName;
private Consumer<CustomerInteractionResult> onComplete
void initialize() {}
void initData(Customer customer, Consumer<CustomerInteractionResult> onComplete) {
customerName.setText(customer.getName());
this.onComplete = onComplete;
}
#FXML
void onSomeInteractionLikeCloseDialog(ActionEvent event) {
onComplete.accept(new CustomerInteractionResult(someDataGatheredByDialog));
}
}
Another way to do this is to add a result property to the controller of the dialog screen and interested invokers could listen to or retrieve the result property. A result property is how the in-built JavaFX dialogs work, so you would be essentially imitating some of that functionality.
If you have a lot of this passing back and forth stuff going on, a shared dependency injection model based on something like Gluon Ignite, might assist you.
I've used AfterBurner.fx for dependency injection, which is very slick and powerful as long as you follow the conventions. It's not necessarily an external lib if you just copy the 3 classes into your structure. Although you do need the javax Inject jar, so I guess it is an eternal reference.
Alternately, if you have a central "screen" from which most of your application branches out you could use property binding probably within a singleton pattern. There are some good articles on using singleton in JavaFX, like this one. I did that for a small application that works really great, but defining all of those bindings can get out of hand if there are a lot of properties.
To pass data back, the best approach is probably to fire custom Events, which the parent controller subscribes to with Node::addEventHandler. See How to emit and handle custom events? for context.
In complex cases when the two controllers have no reference to each other, a Event Bus as #jewelsea mentioned is the superior option.
For overall architecture, this Reddit comment provides some good detail: https://www.reddit.com/r/java/comments/7c4vhv/are_there_any_canonical_javafx_design_patterns/dpnsedh/

How to call a remoteObject method that is outside of my TitleWindow component on Flex?

I have a TitleWindow component. It allows me to save some data provided through 3 TextInput.
That data "fills" a DropDownList which is in another TitleWindow component, not inside the original one.
How can I call the remoteObject method that fills (or refresh) my DropDownList?
Any ideas will be appreciated!
You can simply use a Singleton as a model if you'd like, this will allow you to share data, but beware keep data only that needs to be shared in here or it will just become a global nightmare.
Using a singleton means you'll have a class that you can only ever have one instance of. If you put properties in that class any time you reference it it will be the same memory throughout the application execution.
http://blog.pixelbreaker.com/actionscript-3-0/as30-better-singletons
Marking the singleton class or individual properties as Bindable will make it so you can watch for the changes and call a function.
http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_8.html
Putting this together you have something like this:
[Singleton.as]
package
{
[Bindable]
public class Singleton
{
public var myListData:Array;
public static var instance:Singleton;
public static function getInstance():Singleton
{
if( instance == null ) instance = new Singleton( new SingletonEnforcer() );
return instance;
}
public function Singleton( pvt:SingletonEnforcer )
{
// init class
}
}
}
internal class SingletonEnforcer{}
Somewhere else you want to get a handle on this
[MyTitleWindow.as]
var instance:Singleton = Singleton.getInstance();
instance.myListData = [1,2,3];
[MyTitleWindowWithAList]
var instance:Singleton = Singleton.getInstance();
BindingUtils.bindSetter(funcUpdateList, instance, "myListData");
private function funcUpdateList(data:Object)
{
myList.dataProvider = data as Array;
}
Another option is to create an event that carries your data payload, dispatch that event from the first title window, and capture it, the problem with this is you have to register the listeners on the PopUpManager or SystemManager I believe because the TitleWindow's aren't direct children of the Application I believe.
Singletons are a bad idea and you should not get in the habit of using them. Instead, just dispatch an event from the View and catch it from something else that has access to your Service object.
Note that your Service should not be part and parcel of any View--the responsibility of a View is displaying data and capturing requests from the user to change the data, not communicating with a server.
For examples of an application written with this pattern in mind, check out
[Refactoring with Mate] (http://www.developria.com/2010/05/refactoring-with-mate.html) - The example has View source enabled
The same application done with RobotLegs - again, View Source is enabled.
Note that these are written against some popular frameworks, but they are written in such a way that you can easily replace that framework code with something else, even your own code.
For reference, here is the naiive implementation, where the service layer is being called directly in the Views. You couldn't call a different service without changing the Views, though the use of the static service means you could use it from elsewhere.
That static usage survived into the later examples, though today I would never write something depending on a globally accessible object. In part this is because I discovered Test Driven Development, and it is impossible to replace the "real" static object with an object that lets you isolate what you are testing. However, the fact that most of the code in the 2 "better" examples is insulated from that static object means that it is trivial to replace it with one that is provided some other way.
The lesson here is if you're going to use static, global objects, lock them away behind as much abstraction as you can. But avoid them if you're at all interested in best practice. Note that a Singleton is a static global object of the worst kind.

AS3 How do you access an instance of a class from anywhere?

I currently pass a reference to my model through the constructor to any class that needs it in my simple mvc pattern, this can get annoying at times when it starts to go deeper.
How do Classes such as LoadMax allow you from anywhere to simple import the class, and do something like addChild(LoaderMax.getContent("bg"));? Replicating this should surely be a good way to have my model work, without the complexity of big frameworks?
Statics are your friend
As previous answers have noted, TweenLite/Max etc. makes heavy use of static members to get work done. This is exactly like the Math class, for example, and can be a very convenient design pattern. You have global access to the class, and that can definitely alleviate the issue of getting access to variables through deeply nested classes.
Statics are the enemy
Statics, however, bring certain problems to the table. Most importantly, they tend to reduce flexibility and modularity of classes through the often unnecessary addition of tightly coupled relationships. It's a bit like pouring concrete over your application. It does work, but changing behavior becomes difficult as project features change.
Static members != instance members
Note, very clearly, that a static member "belongs" to the class itself, and not an instance of that class. Static members have no access to instance members. This causes troubles when you want to mix these members up in logic. You tend to have to make everything static (the so-called "static-cling" effect). Static patterns are often argued to be argued to be "anti" object-oriented, for precisely this reason. Once you build a structure on a static pattern you tend to lose many of the principles that makes OOD powerful.
In small does, they're pretty nice
That all being said - TweenLite is a great example of a static pattern that is totally appropriate - its a utility package, one that logic is not dependent on. And that should probably be how you leverage statics, too.
To reduce reliance on statics, or even global vars, it does often mean writing more code, but the flexibility in app structure gained is often quite worth it. #Marty_Wallace has a pretty good solution imo.
Demeter and the Paperboy
Finally, I'll just mention the Law of Demeter, or the Principle of Least Knowledge, and the related Paperboy and the Wallet example, which is often pointed to in discussions of statics:
Each unit should have only limited knowledge about other units: only
units "closely" related to the current
unit.
Each unit should only talk to its friends; don't talk to strangers.
Only talk to your immediate friends.
Hopefully that sheds a little bit of light on a fairly complicated and not-often obvious issue.
This is done using the static namespace, however I discourage the use of this.
package
{
public class Main
{
public static function sayHell():void
{
trace("hello!");
}
}
}
You can now call sayHello() like this from anywhere in the application (assuming you've imported the class).
Main.sayHello();
Another thing you can do (to make the entire class accessible from within the application) is create a static property that refers to the class itself:
package
{
public class Something
{
public static var instance:Something;
public function Something()
{
instance = this;
}
public function someFunction():void
{
trace('hello!');
}
}
}
Which you can now use like so:
Something.instance.someFunction();
The only thing to note here is that you need to create an instance of Something for this to work to call the constructor and define instance.
What I would do
Create a base class for all objects in your application
Create a manager class that takes care of these objects
Create a setter within your base class to define the manager
Here's an example:
Base
package
{
public class Base extends Object
{
private var _manager:Manager;
public function set manager(m:Manager):void
{
_manager = m;
init();
}
protected function init():void
{
manager.someFunction();
}
public function get manager():Manager{ return _manager; }
}
}
Manager
package
{
public class Manager extends Object
{
public function someFunction():void
{
trace('hello!');
}
}
}
Now anything that extends Base will have access to anything held in Manager via the manager getter property. All you need to do is make sure you define the manager, which is easily achieved from within anything that extends Base like so:
var something:SomeExtendingClass = new SomeExtendingClass();
something.manager = manager;
The example you gave is just a static method, but to answer your question about a global instance of a class:
package myPackage
{
public var globalVariable:MyClass = new MyClass();
}
You can access it with:
import myPackage.globalVariable;
trace(globalVariable);
I think you have to rethink in which way you want to name your classes.
You can instantiate whatever class you want, at run-time, but to access a instance by name, you have to make changes in your structure. For example, the getContent() function you mentioned in LoaderMax, all it does is to search in an array for the given loader that matchs the name, among other things. You can read the name variable comment for a description.
A name that you use to identify the loader instance. This name can be fed to the getLoader() or getContent() methods or traced at any time. Each loader's name should be unique. If you don't define one, a unique name will be created automatically, like "loader21".
So in this system, you have to name every single member (loaders in this case) if you want to be able to search them. Because if I call getClassInstance("myinstance"), what is "myinstance" representing? Where should I name it?
That said, if you want to do it for DisplayObjects only, you can use getChildByName. But again, you have to name every DisplayObject (just set the name variable).
Hope this helps.

When should and shouldn't I extend a class, and is it valid for MVC?

I am considering using class extension as a way to connect my model with my controller. I tried looking on the internet but could not find any information on this topic. This led me to the question of when a class should be extended and for what reasons.
This is my plan:
model class
controller extends model
new controller();
new view(controller);
Reason:
I can make all methods and variables that the view should not touch or alter protected (i.e. protected var myVar:String). This enables me to ensure that the view still has access to the data it needs but is unable to make accidental changes.
This whole thought process derived from the fact that I don't want my view to have any influence whatsoever, while still remaining independent (i.e. I can have multiple views of the same model without having to tell the controller that an additional view has been added).
To summarize:
When should a class be extended? When should it be avoided?
Is my plan a valid implementation of MVC?
Is there a better way to disconnect the view in a way that meets my demands?
Thank you for reading till the end.
The controller shouldn't extend the model - they do two separate things in the MVC triad and therefore should be two different classes. A valid reason to extend the Model class would be to add an extra feature to it, for example BigModel
Heres a summary of each part of MVC structure
The model manages the behavior and data of the application domain
The view renders the model into a form suitable for interaction, typically a user interface element
The controller receives input and initiates a response by making calls on model objects.
Your view will not have access to the protected methods of the model/controller. Protected does not mean read only, it means that only classes that extend the base class can access the protected properties or methods.
To have read only attributes in your model you should look at using private/protected properties and then creating a public getter function for each property (Property can then be read but not set).
Also to have access to the model from the view consider creating the Model as a Singleton so it can be accessed from anywhere in your application.
The controller dosen't usually do much else than listen for and dispatch events/notifications, sometimes for small projects you can make your Model class (Singleton) extend EventDispatcher and have it pretty much do everything you want, but this is not pure MVC and can quickly lead to technical debt if the project scope grows.

TDD - Refactoring into black-box?

I have a nontrivial service object developed with TDD. It started with a simple task: For an object from queue, construct an attempt for asynchronous processing. So I wrote a test around my constructAttempt() method:
void constructAttempt() {...}
There are numerous possible scenarios that need to be taken into consideration, so I have a dozen tests for this method.
Then I implemented what I really needed it to do: Scan the whole queue and construct a batch of attempts. So the code looks more like:
public void go() {
for (QueuedItem item : getQueuedItems()) {
constructAttempt(item);
}
}
So I added a new test or two for this go() method.
Finally I discovered I needed some preprocessing which sometimes may affect constructAttempt(). Now the code looks more like:
public void go() {
preprocess();
for (QueuedItem item : getQueuedItems()) {
constructAttempt(item);
}
}
I have a few doubts about what I should do now.
Shall I keep the code as is, with constructAttempt(), preprocess() and go() tested independently? Why yes/why not? I risk not covering side effects of preprocessing and break encapsulation.
Or shall I refactor my whole test suite to only call go() (which is the only public method)? Why yes/why not? This would make tests a little bit more obscure, but on the other hand it would take all possible interactions into consideration. It would in fact become a black-box test using only the public API, what may not be in line with TDD.
The go method is really just orchestrating several interactions, and isn't very interesting in its own right. If you write your tests against go instead of your subordinate methods, the tests are likely be hideously complicated because you'll have to account for the combinatorial explosion of interactions between preprocess and constructAttempt (and maybe even getQueuedItems, though that sounds relatively simple).
Instead, you should write tests for the subordinate methods - and the tests for constructAttempt need to account for all of preprocess' potential effects. If you can't simulate those side-effects (by manipulating the underlying queue or a test double) refactor your class until you can.
#Jeff has it about right. What your really have is two responsibilities occurring in this object. You may want to pull the queued items into their own class. Push the preprocess and constructAttempt into individual items. IMHO when you have a class that deals with individual items and a list of items you have a code smell. The responsibilities are the list container acts on the items.
public void go() {
for (QueuedItem item : getQueuedItems()) {
item.preprocess();
item.constructAttempt();
}
}
Note: This is similar to working with a command object pattern
[EDIT 1a]
This makes it really easy to test with mocking. The go method only need to tests with a single queue item or no queue items. Also each item now can have their individuals tests separate from the combinatorial explosion of the go.
[EDIT 1b]
You might even be able to fold the preprocess into the item:
public void go() {
for (QueuedItem asyncCommunication: getQueuedItems()) {
asyncCommunication.attempt();
}
}
Now you have a true command pattern.
I say let your test suite only call go() since it is the only public API. Which means once you have covered all scenarios for go method (which would include preprocess and queue) then it no longer matters if you change internal implementation. Your class stays correct as far as public use is concerned.
I hope you are using dependency inversion for classes used for preprocessing/queue stuff- that way you can independently test preprocessing and then mock it in your go() test.