Exception/MessageBox in Calibur.Micro - exception

I start learning Caliburn.Micro and I am little confuse of handling with exception/messange box in view model class.
I found some blogs about, for example:
http://frankmao.com/2010/11/18/handling-messagebox-in-caliburn-micro/
For example some method in view model class which can produce exception.
public void MethodWichCanProduceEx(string arg1, string arg2 )
{
if(arg1==null)
throw new ArgumentNullException("arg1 is null");
if (arg2 == null)
throw new ArgumentNullException("arg2 is null");
try
{
}
catch (Exception exception)
{
throw exception;
//? show message box MessageBox.Shox(exception.Message)
}
}
What is correct handling and showing these exception in view ? It exist any kind of pattern for caliburn.micro?
It possible trace exception as in .NET in text, xml file ?
For example I would like trace exception in xml, text file and in view show only message.box or something message.
Thank for advance, maybe is my question little stupid, sorry I am only learning calibur.micro.

You'll want to always work against abstractions in your view models, in the case of message boxes, you don't want to have to wait for user input when you come to unit test your view models.
The Frank Mao code you linked to uses a delegate to abstract the implementation of the message box from the view model, but I would use an interface here. You can think of a delegate as an interface with a single method, but the advantage of using an interface in this context is that you can have different methods depending on the type of message you wish to show. For example, you could have a ShowMessageError, ShowMessageWarning, ShowMessageInfo etc.
So, define a contract for your message box:
public interface IMessageBox
{
void ShowException(Exception exc);
}
Inject the message box dependency into your view model, e.g. via the constructor
public class MyViewModel
{
private readonly IMessageBox messageBox;
public MyViewModel(IMessageBox messageBox)
{
this.messageBox = messageBox;
}
public void MethodThatCanThrowException()
{
try {}
catch(Exception exc)
{
// log the exception here
...
// show message box
this.messageBox.ShowException(exc);
}
}
}
You can then implement the message box anyway you wish, either using the windows system message box, or nicer still use your own view/viewmodel to display the message, perhaps using the Caliburn.Micro WindowManager.ShowDialog().
An implementation that uses the windows system message box may look like:
public class StandardMessageBox : IMessageBox
{
public void ShowException(Exception exception)
{
MessageBox.Show(exception.ToString(), "Error Occurred");
}
}
In production code, you can register StandardMessageBox against the IMessageBox interface in your IoC container.
In unit test land, you can mock out IMessageBox and have it do nothing, or in the case of methods with a result from the message box, always return a value you wish.
For logging the exception, I would look at a logging framework such as log4net (http://logging.apache.org/log4net/index.html) or NLog (http://nlog-project.org/)

Related

How to skip static validation in JUnit test with Mockito

I have a function I need to test:
#Override
public ResponseEntity<BasicResponse> myFunction(HttpServletRequest request, #RequestBody Dto dto, BindingResult result) {
try {
ValidationUtils.invokeValidator(validator, dto, result);
if (result.hasErrors()) {
// do things
} else {
//do things
}
} catch (Exception e) {
// catch
}
//return things;
}
But when I test the function it always go to the catch because of the validator, it says:
"Validator does not support Dto".
I don't care about the validation, I need to test what's inside the try, so I try to use doNothing to skip the validation but I get an error because it's void:
#Test
void TestMyFunction() {
doNothing().when(ValidationUtils.invokeValidator(validator, dto, result));
ResponseEntity<BasicResponse> response = controller.myFunction(request, dto, result);
// assert something
}
Any idea on how to proceed? I can't change the function, I can only write the test and I'm new at this. Thank you.
If ValidationUtils was an object instance that is a Mockito spy or mock, you would be able to mock it like so:
doNothing()
.when(validationUtils)
.invokeValidator(validator, dto, result);
This, unfortunately, does not seem to be the case in your test - ValidationUtils seems to be a class on which a static method is called, which Mockito can handle since version 3.4.0 (before that it was usually handled by PowerMock). thenAnswer should be used with the mockedStatic object instance, similarly to this answer, since the method's return type is void.
An important additional (but mandatory) note: mocking static methods is discouraged and should be avoided whenever possible. It slows down the tests and is a sign of bad design of the classes. The validator should be injected into the class or created using a factory, thanks to that a mocked object instance could be easily used.
I've checked that and in fact the thenAnswer part is not required to do nothing after using mockStatic on a class.
try (var mockedStatic = Mockito.mockStatic(ValidationUtils.class)) {
// test code
}
The code above makes ValidationUtils do nothing and return default values (0, false, null).
See this example (all tests pass).

JUnit5 react to #Before* methods failure

Is there any hook in Junit5 that reacts to fails in #Before* methods?
I use a #BeforeAll method to init environment for my tests. But this initialization may sometimes fail. I want to dump the environment, to find out whats wrong, but I need to do it before #After* methods are called, which will clear the environment and destroy all info.
We're talking about dozens of these #BeforeAll methods across the test suite, so doing it manually inside each method is not an option.
I've already tried these, but no luck:
TestWatcher does not work for this, since it only fires if an actual test is executed.
TestExecutionListener.executionFinished looks promising, but it fires after all the #After methods, which is too late for me.
I even tried to do it inside the #AfterAll cleanup methods, before the actual cleanup. But found no way to detect which tests were executed or if anything failed.
Any ideas?
I assume by "fails in #Before* methods" you mean exceptions? If that is the case, you could leverage the extension model as follows:
#ExtendWith(DumpEnvOnFailureExtension.class)
class SomeTest {
static class DumpEnvOnFailureExtension implements LifecycleMethodExecutionExceptionHandler {
#Override
public void handleBeforeAllMethodExecutionException(final ExtensionContext context, final Throwable ex)
throws Throwable {
System.out.println("handleBeforeAllMethodExecutionException()");
// dump env
throw ex;
}
}
#BeforeAll
static void setUpOnce() {
System.out.println("setUpOnce()");
throw new RuntimeException();
}
#Test
void test() throws Exception {
// some test
}
#AfterAll
static void tearDownOnce() {
System.out.println("tearDownOnce()");
}
}
The log will be:
setUpOnce()
handleBeforeAllMethodExecutionException()
tearDownOnce()
That is, the extension is notified if the #BeforeAll method fails with an exception. (Note that this is just an MWE, for the actual implementation you would extract DumpEnvOnFailureExtension and use it wherever needed.)
For further information, check out section "Exception Handling" in the user guide.

Is it possible to bind hiding/showing a UIAlertController in Mvvmcross?

I have a command which interacts with an API. If the command doesn't return a desired result it sets a property of the ViewModel called Error.
I want to bind Error to a UIAlertController in my View and have it display when the error occurs.
Here's roughly what I have (although obviously the visibility converter isn't the way to go). I should add that I'm aware PresentViewController should be used to display the UIAlertController.
UIAlertController myAlert = UIAlertController.Create ("", Error.Text, UIAlertControllerStyle.Alert);
set.Bind(myAlert).For("Visibility").To((myViewModel vm) => vm.Error).WithConversion("Visibility");
Check out Observer design pattern.
The way I prefer to achieve that is simple:
Create class which inherits from MvxMessage - let say ShowAlertDialogMessage with properties like title, content and so on.
Create abstract MessageObserver where TMessage : MvxMessage class, ex.:
public interface IMessageObserver
{
void Subscribe(IMvxMessenger messenger);
void Unsubscribe();
}
public abstract class MessageObserver<TMessage> : IMessageObserver where TMessage : MvxMessage
{
public void Subscribe(IMvxMessenger messenger) {
messenger.SubscribeOnMainThread<TMessage>(OnMessageDelivered);
}
public abstract void OnMessageDelivered(TMessage message);
}
Create MessageObserverController
public class MessageObserverController {
public void SubscribeObserver(IMessageObserver msgObserver) {
msgObserver.Subscribe(messenger);
}
.. unsubscribe, dispose and so on goes here
}
Implement ShowAlertDialogMessageObserver class (inherit from MessageObserver<ShowAlertDialogMessage>() which shows UIAlertViewController with data from ShowAlertDialogMessage (title, content and so on). Pass root UIViewController as constructor if needed (you will register MessageObservers in your viewcontrollers anyway - so that's not a problem).
Use MessageObserverController in your ViewControllers (preferably create base view controller to simplify things).
VoilĂ  - you get reusable UI logic, which you can raise by publishing message in your PCL ViewModel (without creating any platform-specific coupling!).

MVVMCross ViewModel construction failure notifications

We've noticed a couple of times in our mobile applications that users have reported the application hanging or seeming to become unresponsive between views / rare crashes when switching between views. We've tracked down these cases to when our view model constructors throw uncaught exceptions.
We want to put a solution in place so that if a view model fails to construct for some reason then we can notify the user and provide some message that will be useful to us when it's logged through support.
I've been taking a look at doing this but haven't found a reliable way to achieve this.
The first thing we tried was at the IMvxViewModelLocator level. We already have a custom implementation of IMvxViewModelLocator so we've modified this. We allow all exceptions to be thrown and then we have an IErrorHandler interface which each platform implements. We then call this to attempt to show a dialog. This has proved to be unreliable and the dialog does not always display. Something along the lines of: (note - here ResolveViewModel will always return true or throw)
public override bool TryLoad(Type viewModelType, IMvxBundle parameterValues, IMvxBundle savedState, out IMvxViewModel viewModel)
{
try
{
return ResolveViewModel(viewModelType, parameterValues, savedState, out viewModel);
}
catch (Exception exception)
{
_errorHandler.HandleViewModelConstructionException(viewModelType, exception);
viewModel = null;
return false;
}
}
What we would ideally like to do is intercept any failure to construct a view model and then re-request an ErrorViewModel. We've tried to do this 2 ways:
1)
We've tried defining a custom IMvxViewDispatcher for each platform and we're trying to intercept failures as below but if an exception in the constructor is thrown we never get back this far:
public class TouchDispatcher : MvxTouchUIThreadDispatcher, IMvxViewDispatcher
{
private readonly IMvxTouchViewPresenter _presenter;
public TouchDispatcher(IMvxTouchViewPresenter presenter)
{
_presenter = presenter;
}
public bool ShowViewModel(MvxViewModelRequest request)
{
Action action = () =>
{
_presenter.Show(request);
};
try
{
bool success = RequestMainThreadAction(action);
return !success ? HandleError() : success;
}
catch (Exception)
{
return HandleError();
}
}
// Other bits
}
2)
We thought we might have more success at the presenter level. We modified our ViewPresenter for each platform and we have overridden void Show(MvxViewModelRequest request). This has not proved to be successful either as exceptions don't propagate back this far.
This leaves me thinking that maybe we are better attempting this at the IMvxViewModelLocator level again.
Has anyone found a way to reliably intercept failures to construct view models and then ideally re-request a different view model / present some dialog to the user?
It seems you've identified that the core of the problem is when: "view model constructors throw uncaught exceptions."
This is going to be slightly problematic as the ViewModel's are generally constructed during View lifecycle overrides like ViewDidLoad, OnCreate or NavigatedTo - which is generally after the Presenter has finished requesting presentation.
As you've already found an easy place to identify when ViewModel construction has failed is in a custom IMvxViewModelLocator - others likeIMvxViewModelLoader are also possible. This is probably the easiest place to catch the error and to trigger the error handling - you can then get hold of the IMvxViewDispatcher (or presenter) there in order to change the display. However, you will still need to make sure your Views can handle null created ViewModels - as the ViewDidLoad, etc calls will still need to complete.

Communication between layers in an application

Let's assume we have the following method in the business layer. What's the best practice to tell the UI layer that something went wrong and give also the error message? Should the method return an empty String when it was OK, otherwise the error message, or should it throw another exception in the catch code wrapping the caught exception? If we choose the second variant then the UI should have another try,catch which is too much try,catch maybe. Here is a pseudocode for the first variant.
public String updateSomething()
{
try
{
//Begin transaction here
dataLayer.do1();
dataLayer.do2();
dataLayer.doN();
//Commit transaction code here
}
catch(Exception exc)
{
//Rollback transaction code here
return exc.message;
}
return "";
}
Is this a good practice or should I throw another exception in the catch(then the method will be void)?
I like to return a standard contract to my UI layer from my business layer.
It looks like this:
public class ServiceOperationResult<T>
{
public bool Successful
{
get;
set;
}
public ServiceErrorType ErrorType
{
get;
set;
}
public string ErrorMessage
{
get;
set;
}
public T ReturnData
{
get;
set;
}
}
I use generics so that every service can define what it sends back, and the standard error flags tell the client app what type of error occurred (these are a meta-type, like "Internal error", "External party error", "Business rule validation error") and the app can then react in a standard fashion to these error types.
For instance, business errors are displayed in a red error label, while internal errors get redirected to an error page (in a web app) or close the form (in a windows app)
My pet hate is seeing a red label on a web site (where I expect to see validation errors) and seeing something like "The database server refused your connection" This is the risk that you run by only using a string to return error data.
The best way is wrap exception in some more general type and rethrow it. So updateSomething() must declare that it can throw some sort of Exception (for example: UpdateFailedException) and in catch block you should wrap exception.
public String updateSomething() {
try {
[...]
} catch ( SQLException e ) {
// rollback;
throw new UpdateFailedException(e);
}
}
But catching abstract Exception type is not a good idea. You should wrap only those things which semantic you know. For example: SQLException, DataAccessException (Spring DAO) etc.
If you wrap Exception you easily could wrap InterruptedException of NullPointerException. And this can broke your application.
It's a little unusual to return a String like this (but there's no real reason not too). More usual methods would be:
return a boolean value, and have some method of setting the error message, either by logging it, setting some global "last error" value, or having a pointer to an error construct passed in to your method which you update;
have a void method which throws an exception on failure, and handle it in the calling code (as you suggest)
I have see both of the above used extensively. It's hard to say which is "best". Try to be consistent with the idioms and conventions of the language you are working in and/or the existing code set/libraries you are working with if any.
Probably the best way is to have a custom exception classes specific to layers, once you catch the exception in a particular layer throw the custom exception to the calling layer, having this will have you the following advantage.
you will get the better modular approach to deal with the exception.
the maintenance of the code will be easy when your code complexity increases
you will be having more control on the exception scenarios
for example you catch a exception in the business layer and want to inform Presentation layer
public string DummyFunction
{
try
{
}
catch(Exception ex)
{
throw new businessException();
}
}