I want to unit test the custom controls I create for a windows store project. Just simple things like "there is a button when X is true".
However, I can't seem to even instantiate the controls in a testing context. Whenever I try to invoke the constructor, I get an exception related to not being run in the UI context. I've also been unable to create coded UI test projects that target windows store projects.
How do I programmatically instantiate a control to test? How do I create a WinRT UI synchronization context?
How do I programmatically send "user" command events to a control?
How do I programmatically instantiate/teardown the entire application?
I've found a hacky way to make non-interactive parts work: with the function Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync.
Obvious, right? However, this still leaves open the question of how to emulate user actions.
/// Runs an action on the UI thread, and blocks on the result
private static void Ui(Action action) {
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() => action()
).AsTask().Wait();
}
/// Evaluates a function on the UI thread, and blocks on the result
private static T Ui<T>(Func<T> action) {
var result = default(T);
Ui(() => { result = action(); });
return result;
}
[TestMethod]
public void SliderTest() {
// constructing a Slider control is only allowed on the UI thread, so wrap it in UI
var slider = Ui(() => new Slider());
var expected = 0;
// accessing control properties is only allowed on the UI thread, so same deal
Assert.AreEqual(expected, Ui(() => slider.Value));
}
Related
I am having an MvvmCross ViewModel, which calls different async methods of my DataService.
Similar to the following:
public class LoginViewModel : MvxViewModel
{
private readonly IIdentityService _dataService;
private CancellationTokenSource _viewModelCancellationTokenSource;
public IMvxCommand GoLogin { get; set; }
public LoginViewModel(IIdentityService identityService)
{
_dataService = identityService;
_viewModelCancellationTokenSource = new CancellationTokenSource();
GoLogin = new MvxCommand(async () => await ProcessLogin());
}
private async Task ProcessLogin()
{
// calling the dataservice which must stop processing
// (to cancel) in case if the ViewModel is being destroyed
await _dataService.AssureIsLoggedIn(data, _viewModelCancellationTokenSource.Token);
await NavigationService.Navigate<LoginNextStepViewModel>();
}
public override void ViewDestroy(bool viewFinishing = true)
{
base.ViewDestroy(viewFinishing);
// not sure if that is a right (and working) place
_viewModelCancellationTokenSource.Cancel();
}
}
So, MvvmCross is quite unclear about the part with the ViewModel destroying. It describes Construction, Init, Reload and Start, but doesn't say any definite regarding the destroying:
Monitoring other View/ViewModel lifecycle event across multiple
platforms is fairly tricky, especially once developers start
experimenting beyond the ‘basic’ presentation models and start using
tabs, splitviews, popups, flyouts, etc
For most viewmodels, it’s common to not try to monitor other lifecyle
events. This is OK since most viewmodels don’t perform any actions and
don’t consume any resources when the view is not present - so these
can just be left to be garbage collected when the system needs the
memory back.
However, besides the custom platform situations, there are still many cases like navigating back from the view model, or (again) navigation away from current viewmodel with its following closing.
So, what's the best way to handle it then?
From your code:
// calling the dataservice which must stop processing
// (to cancel) in case if the ViewModel is being destroyed
The ViewModel won't be destroyed before the async methods finish executing. I think you are confusing the View with the ViewModel.
In case of a login page, you would usually prevent the user from navigating away from it until your server call goes through.
If for some reason you want to cancel then you need to decide what scenarios you want to handle, there is no single universal place. Your options are the view callbacks:
void ViewDisappearing();
void ViewDisappeared();
void ViewDestroy();
and the navigation events:
event BeforeNavigateEventHandler BeforeNavigate;
event AfterNavigateEventHandler AfterNavigate;
event BeforeCloseEventHandler BeforeClose;
event AfterCloseEventHandler AfterClose;
event BeforeChangePresentationEventHandler BeforeChangePresentation;
event AfterChangePresentationEventHandler AfterChangePresentation;
My code looks like this:
public void Init() {
if (AS.pti == PTI.UserInput)
{
AS.runCardTimer = false;
}
else
{
AS.runCardTimer = true;
Device.BeginInvokeOnMainThread(() => showCards().ContinueWith((arg) => { }));
}
}
The Init method is called from the constructor. Can someone please explain to me why the developer might have added the Device.BeginInvokeOnMainThread() instead of just calling the method showCards?
Also what does the ContinueWith((arg)) do and why would that be included?
The class where this Init() method is might be created on a background thread. I'm assuming showCards() are updating some kind of UI. UI can only be updated on the UI/Main thread. Device.BeginInvokeOnMainThread() ensures that the code inside the lambda is executed on the main thread.
ContinueWith() is a method which can be found on Task. If showCards() returns a task, ContinueWith() makes sure the task will complete before exiting the lambda.
UI actions must be performed on UI thread (different name for main thread). If you try to perform UI changes from non main thread, your application will crash. I think developer wanted to make sure it will work as intended.
The simple answer is: Background thread cannot modify UI elements because most UI operations in iOS and Android are not thread-safe; therefore, you need to invoke UI thread to execute the code that modifies UI such MyLabel.Text="New Text".
The detailed answer can be found in Xamarin document:
For iOS:
IOSPlatformServices.BeginInvokeOnMainThread() Method simply calls NSRunLoop.Main.BeginInvokeOnMainThread
public void BeginInvokeOnMainThread(Action action)
{
NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke);
}
https://developer.xamarin.com/api/member/Foundation.NSObject.BeginInvokeOnMainThread/p/ObjCRuntime.Selector/Foundation.NSObject/
You use this method from a thread to invoke the code in the specified object that is exposed with the specified selector in the UI thread. This is required for most operations that affect UIKit or AppKit as neither one of those APIs is thread safe.
The code is executed when the main thread goes back to its main loop for processing events.
For Android:
Many People think on Xamarin.Android BeginInvokeOnMainThread() method use Activity.runOnUiThread(), BUT this is NOT the case, and there is a difference between using runOnUiThread() and Handler.Post():
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);//<-- post message delays action until UI thread is scheduled to handle messages
} else {
action.run();//<--action is executed immediately if current running thread is UI thread.
}
}
The actual implementation of Xamarin.Android BeginInvokeOnMainThread() method can be found in AndroidPlatformServices.cs class
public void BeginInvokeOnMainThread(Action action)
{
if (s_handler == null || s_handler.Looper != Looper.MainLooper)
{
s_handler = new Handler(Looper.MainLooper);
}
s_handler.Post(action);
}
https://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)
As you can see, you action code is not executed immediately by Handler.Post(action). It is added to the Looper's message queue, and is handled when the UI thread's scheduled to handle its message.
I have an ICEfaces web app which contains a component with a property linked to a backing bean variable. In theory, variable value is programmatically modified, and the component sees the change and updates its appearance/properties accordingly.
However, it seems that the change in variable isn't "noticed" by the component until the end of the JSF cycle (which, from my basic understanding, is the render response phase).
The problem is, I have a long file-copy operation to perform, and I would like the the inputText component to show a periodic status update. However, since the component is only updated at the render response phase, it doesn't show any output until the Java methods have finished executing, and it shows it all changes accumulated at once.
I have tried using FacesContext.getCurrentInstance().renderResponse() and other functions, such as PushRenderer.render(String ID) to force XmlHttpRequest to initialize early, but no matter what, the appearance of the component does not change until the Java code finishes executing.
One possible solution that comes to mind is to have an invisible button somewhere that is automatically "pressed" by the bean when step 1 of the long operation completes, and by clicking it, it calls step 2, and so on and so forth. It seems like it would work, but I don't want to spend time hacking together such an inelegant solution when I would hope that there is a more elegant solution built into JSF/ICEfaces.
Am I missing something, or is resorting to ugly hacks the only way to achieve the desired behavior?
Multithreading was the missing link, in conjunction with PushRenderer and PortableRenderer (see http://wiki.icesoft.org/display/ICE/Ajax+Push+-+APIs).
I now have three threads in my backing bean- one for executing the long operation, one for polling the status, and one "main" thread for spawning the new threads and returning UI control to the client browser.
Once the main thread kicks off both execution and polling threads, it terminates and it completes the original HTTP request. My PortableRenderer is declared as PortableRender portableRenderer; and in my init() method (called by the class constructor) contains:
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
For the threading part, I used implements Runnable on my class, and for handling multiple threads in a single class, I followed this StackOverflow post: How to deal with multiple threads in one class?
Here's some source code. I can't reveal the explicit source code I've used, but this is a boiled-down version that doesn't reveal any confidential information. I haven't tested it, and I wrote it in gedit so it might have a syntax error or two, but it should at least get you started in the right direction.
public void init()
{
// This method is called by the constructor.
// It doesn't matter where you define the PortableRenderer, as long as it's before it's used.
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
}
public void someBeanMethod(ActionEvent evt)
{
// This is a backing bean method called by some UI event (e.g. clicking a button)
// Since it is part of a JSF/HTTP request, you cannot call portableRenderer.render
copyExecuting = true;
// Create a status thread and start it
Thread statusThread = new Thread(new Runnable() {
public void run() {
try {
// message and progress are both linked to components, which change on a portableRenderer.render("fullFormGroup") call
message = "Copying...";
// initiates render. Note that this cannot be called from a thread which is already part of an HTTP request
portableRenderer.render("fullFormGroup");
do {
progress = getProgress();
portableRenderer.render("fullFormGroup"); // render the updated progress
Thread.sleep(5000); // sleep for a while until it's time to poll again
} while (copyExecuting);
progress = getProgress();
message = "Finished!";
portableRenderer.render("fullFormGroup"); // push a render one last time
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
});
statusThread.start();
// create a thread which initiates script and triggers the termination of statusThread
Thread copyThread = new Thread(new Runnable() {
public void run() {
File someBigFile = new File("/tmp/foobar/large_file.tar.gz");
scriptResult = copyFile(someBigFile); // this will take a long time, which is why we spawn a new thread
copyExecuting = false; // this will caue the statusThread's do..while loop to terminate
}
});
copyThread.start();
}
I suggest looking at our Showcase Demo:
http://icefaces-showcase.icesoft.org/showcase.jsf?grp=aceMenu&exp=progressBarBean
Under the list of Progress Bar examples is one called Push. It uses Ajax Push (a feature provided with ICEfaces) to do what I think you want.
There is also a tutorial on this page called Easy Ajax Push that walks you through a simple example of using Ajax Push.
http://www.icesoft.org/community/tutorials-samples.jsf
Here is what I am trying to do. In my WP7 app, I am loading a page that has two StackPanels. StackPanel1 is "Collapsed" and StackPanel2 is "Visible". On load of the page, I am kicking off an HttpWebRequest and then processing the BeginGetResponse asynchronously. At this point I just want to swap the Visibility of the two StackPanels. However, since the BeginGetResponse is run Asynchronously, I am no longer in the UI thread and cannot manipulate these StackPanel controls. If I try to reference them, of course, I get "An object reference is required for the non-static field, method, or property 'blah.StackPanel1'"
This all makes sense and I get why.
Here are some things I have tried:
Delegates, but any way I sliced it, I needed a static reference to my controls. fail.
I tried to create a static reference to my page class and then use that to reference my controls in the BeginGetResponse. This compiled, but I got a UnauthorizedAccessException 'invalid cross-thread access.' at run-time when I tried to reference the controls.
Searching and searching and searching.
Using Deployment.Current.Dispatcher.BeginInvoke to run on the UI thread.
How can I statically reference these controls?
OR is there a better way to do what I'm doing?
EDIT:
Here is my HttpWebRequest
if (NetworkInterface.GetIsNetworkAvailable())
{
HttpWebRequest httpWebRequest = HttpWebRequest.CreateHttp("http://urlThatWorks.com");
httpWebRequest.Method = "GET";
httpWebRequest.BeginGetResponse((asyncresult) =>
//do processing of my return here
//then here is the problem
StackPanel1.Visibility = System.Windows.Visibility.Visible;
StackPanel2.Visibility = System.Windows.Visibility.Collapsed;
}, httpWebRequest);
}
ANOTHER EDIT:
And here is how I tried with Deployment.Current.Dispatcher.BeginInvoke
httpWebRequest.BeginGetResponse((asyncresult) =>
//do processing of my return here
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
StackPanel1.Visibility = System.Windows.Visibility.Visible;
StackPanel2.Visibility = System.Windows.Visibility.Collapsed;
});
}, httpWebRequest);
You don't really want a static reference, you want a thread-safe way of accessing them.
You can execute it on the UI thread by:
Deployment.Current.Dispatcher.BeginInvoke(()=> SomeMethod);
or
Deployment.Current.Dispatcher.BeginInvoke(()=> { // code });
I'd like to pair a Model with it's View through an interface. I want to control when and how often the view is updated. So something like PropertyChangeListener wouldn't work well (where an event is fired after each property is set).
I'm not developing for a specific GUI framework. The goal here is the ability to swap out different GUI front ends (right now for testing, but might be useful later for different versions of the app). These might be Swing, or it might be a web browser (via GWT, for example).
Below is my approach. The view implements an interface to provide a method to update. This is triggered by the controller when it determines it's done updating the model. This still feels ok to me, since the Controller is only interacting with the view through the model, the controller is not dependent on a particular implementation of the View.
So, I guess my question(s) are
does this work well?
Is this standard practice?
Does this pattern have a name?
Rough code sample (Java):
// Controller, manages Items (the model)
class ItemList {
void addItem(Item item) {
}
void doStuffWithItems() {
// perform some set of operations, such as sorting or layout
for (Item item : items) {
// ....
}
// now with everything in it's final position:
for (Item item : items) {
item.updateView();
}
}
}
// Model
class Item {
private int top;
private int left;
private int width;
private int height;
// Can remember it's previous position/size:
public void savePostion() {
}
// And recall it for the Controller to use:
public public Position getSavedPosition() {
}
// Plus some other useful functions:
public boolean intersectsWith(Item other) {
}
public void updateView() {
this.view.update();
}
void setView(ItemView view) {
this.view = view;
}
}
// Interface used by View implementations
public interface ItemView {
// Trigger the view to reflect the current state of the model
void update();
}
// Example, as a Swing component
class ItemComponent extends JComponent implements ItemView {
private Item item;
public ItemComponent(Item item) {
this.item = item;
item.setView(this);
}
// ItemView#update
public void update() {
// update the component's size/position
setBounds(new Rectangle(item.getLeft(), item.getTop(), item.getWidth(), item.getHeight()));
}
#Override
public void paint(Graphics g) {
// ...
}
}
I would avoid forcing the View to implement an interface only for change notification. Create a separate "update now" event on the model instead.
The model should not be controlling or know about the view directly. The view should register a callback with the controller so the controller can tell the view when to update, that's why its the controller. You could have the model allow external listeners for a modelChangedEvent. Then the view could register with the model in that respect without the model knowing there was a view. See the J2EE blueprint for MVC and how there is an indirect event notification of state change in the model.
For traditional applications that run on the desktop of a computer I recommend variants of the Passive View. The class responsible for creating and managing the form is a thin shell that passes events to the UI Object. The UI_Object interact with the form via a interface. In term the UI Object implements a UI_View Interface and registers itself with a View Controller that is situated lower in the object hierarchy.
The UI_Object then execute object implementing the Command Pattern which modifies the model. The command object can interacts with the various views via the interfaces exposed by the View Control.
What this does is allow you to rip off the form classes and replace them with stub classes that implement the form interfaces. The stub classes are used for automated testing especially for integration tests.
The interfaces precisely define the interaction between the Form, the UI_Object, Commands and the views. They can be designed to be relatively language agnostic so they can make porting between platform easier.
What you are missing in your example are command objects. You need this structure
ItemViewForms
ItemViewImplementation
ItemViewFormInterface
ItemViewCommands
ItemViewInterface
MyModel
Incorporate ItemList in the ItemViewImplementation
ItemComponent would register with the ItemViewImplementation using the ItemViewInterface.
The sequence of events would look something like this
User wants to update the Item
Clicks on the UI (assuming that UI
involves clicking with a mouse)
The Form tells the
ItemViewImplementation through the
ItemViewInterface that X has been
done with Y parameters.
The ItemViewImplementation then
creates a command object with the
parameters it needs from Y.
The Command Object take the Y
Parameters modifies the model and
then tells the
ItemViewImplementation through the
ItemViewInterface to update the UI.
The ItemViewImplementation tells the
ItemViewForms to update the UI
through the ItemViewFormInterface.
The ItemViewForms updates.
The advantage of this approach is that the interaction of each layer is precisely defined through interfaces. The Software ACTIONS are localized into the command objects. The Form layers is focused on display the result. The View layer is responsible for routing actions and response between the Commands and Forms. The Commands are the only things modifying the model. Also you have the advantage of ripping off the Forms Implementation to substitute any UI you want including mock object for unit testing.