The function has return type of 'FutureOr<User>', but doesn't end with a return statement - flutter

I am trying to create a repository for use cases of FirebaseAuth and can see warnings!
Should I ignore the warning, as it not impacting the app?
OR should I handle it now, and How?

Dart has analyzed your program and found out that you have not handled all cases how the method can exit. This is a potentially a problem since your method signature specifies that you method are returning a Future<User> object.
In your case you have not handled the case where an exception are throw from the createUserWithEmailAndPassword method. If an exception are catch, you ends up with a execution path without any return statement.
In this case, Dart will at runtime just return null so it is not an error. But it is a potential sign of a code error since it it not unlikely that you have forgotten the handling of the exception by not have any return statement.
If it is your intention to just return null in case of an exception, you should therefore have insert return null; in both of your catch blocks (or just at the bottom of your method outside the catch-blocks).
Alternative, you can rethrow the exception if you just want to add some logging but still let the caller to also handle the exception. You can read more about this in the language tour: https://dart.dev/guides/language/language-tour#catch
In either cases, you should describe the behavior in the documentation of the method.

Related

Autofac - (Global) Handler/Middleware to unwrap exceptions

We would like to add a handler/middleware to Autofac to essentially unwrap any Autofac.Core.DependencyResolutionException; to throw the inner exception.
Hooking the Activation (or RegistrationPipelineStart) Pipeline phases (using the following code) unwraps one of the exceptions, but the exception ultimately get wrapped by another DependencyResolutionException.
container.RegisterServiceMiddleware<IOController>(PipelinePhase.ResolveRequestStart, (context, next) =>
{
try
{
next(context);
}
catch (Exception ex)
{
// This unwraps one exception, but even if this is done another exception is wrapped.
// If the inner exception is not thrown, there is a DependencyResolutionException wrapped in another DependencyResolutionException
throw ex.InnerException;
}
});
Irrespective of the phase, I always end up with the exception being wrapped.
I think I need to override the behaviour of ActivatorErrorHandlingMiddleware, but I cannot see a way to do this.
(I understand that Constructors should be lightweight an not throw exceptions, but we have a very large application, and are in the process of refactoring the internals...this will take several versions/iterations, so not really a possibility).
Many Thanks in advance.

What's the difference between assert(), Exception, Error in Dart? [duplicate]

Dart explicitly makes a distinction between Error, that signals a problem in your code's logic and should never happen and should never be caught and Exceptions that signal a problem based on run-time data.
I really like this distinction but I wonder when should I then use assert() functions?
Asserts are ways to perform code useful in development only, without hindering the performances of release mode – usually to prevent bad states caused by a missing feature in the type system.
For example, only asserts can be used to do defensive programming and offer a const constructor.
We can do:
class Foo {
const Foo(): assert(false);
}
but can't do:
class Foo {
const Foo() { throw 42; }
}
Similarly, some sanity checks are relatively expensive.
In the context of Flutter, for example, you may want to traverse the widget tree to check something on the ancestors of a widget. But that's costly, for something only useful to a developer.
Doing that check inside an assert allows both performance in release, and utility in development.
assert(someVeryExpensiveCheck());
Background
In Dart an Exception is for an expected bad state that may happen at runtime. Because these exceptions are expected, you should catch them and handle them appropriately.
An Error, on the other hand, is for developers who are using your code. You throw an Error to let them know that they are using your code wrong. As the developer using an API, you shouldn't catch errors. You should let them crash your app. Let the crash be a message to you that you need to go find out what you're doing wrong.
An assert is similar to an Error in that it is for reporting bad states that should never happen. The difference is that asserts are only checked in debug mode. They are completely ignored in production mode.
Read more on the difference between Exception and Error here.
Next, here are a few examples to see how each is used in the Flutter source code.
Example of throwing an Exception
This comes from platform_channel.dart in the Flutter repo:
#optionalTypeArgs
Future<T?> _invokeMethod<T>(String method, { required bool missingOk, dynamic arguments }) async {
assert(method != null);
final ByteData? result = await binaryMessenger.send(
name,
codec.encodeMethodCall(MethodCall(method, arguments)),
);
if (result == null) {
if (missingOk) {
return null;
}
throw MissingPluginException('No implementation found for method $method on channel $name');
}
return codec.decodeEnvelope(result) as T;
}
The MissingPluginException here is a planned bad state that might occur. If it happens, users of the platform channel API need to be ready to handle that.
Example of throwing an Error
This comes from artifacts.dart in the flutter_tools repo.
TargetPlatform _currentHostPlatform(Platform platform) {
if (platform.isMacOS) {
return TargetPlatform.darwin_x64;
}
if (platform.isLinux) {
return TargetPlatform.linux_x64;
}
if (platform.isWindows) {
return TargetPlatform.windows_x64;
}
throw UnimplementedError('Host OS not supported.');
}
First every possibility is exhausted and then the error is thrown. This should be theoretically impossible. But if it is thrown, then it is either a sign to the API user that you're using it wrong, or a sign to the API maintainer that they need to handle another case.
Example of using asserts
This comes from overlay.dart in the Flutter repo:
OverlayEntry({
required this.builder,
bool opaque = false,
bool maintainState = false,
}) : assert(builder != null),
assert(opaque != null),
assert(maintainState != null),
_opaque = opaque,
_maintainState = maintainState;
The pattern in the Flutter source code is to use asserts liberally in the initializer list in constructors. They are far more common than Errors.
Summary
As I read the Flutter source code, use asserts as preliminary checks in the constructor initializer list and throw errors as a last resort check in the body of methods. Of course this isn't a hard and fast rule as far as I can see, but it seems to fit the pattern I've seen so far.
As asserts are ignored in production mode, you should use them as way to do initial tests to your code logic in debug mode:
In production code, assertions are ignored, and the arguments to assert aren’t evaluated.
When exactly do assertions work? That depends on the tools and framework you’re using:
Flutter enables assertions in debug mode.
Development-only tools such as dartdevc typically enable assertions by default.
Some tools, such as dart and dart2js, support assertions through a command-line flag: --enable-asserts.
In production code, assertions are ignored, and the arguments to assert aren’t evaluated.
Refer:https://dart.dev/guides/language/language-tour#assert

How to handle errors for ParameterizedQuery?

The docs for ParameterizedQuery state:
The type can be used in place of the query parameter, with any query method directly. And it never throws any error, leaving it for query methods to reject with ParameterizedQueryError.
What exactly does this mean?
does it mean that the constructor of ParameterizedQuery never throws an error or does it never throw when we execute the query?
how are we supposed to handle the errors?
i.e. when are we supposed to throw ParameterizedQueryError?
E.g. currently my function looks like this:
async foo() {
const pq = new ParameterizedQuery({
text: 'Select ..',
values: [repoRequest.limit],
rowMode: 'array'
});
return transaction.manyOrNone(pq);
}
and it seems to work fine (same as with a text-query parameter) - it will also throw an error at execution time, when the query is erronous.
does it mean that the constructor of ParameterizedQuery never throws an error or does it never throw when we execute the query?
Yes. Errors from Parameterized Queries manifest themselves in the same way as with all queries in the library - through promise rejection.
UPDATE
I have removed that sentence from the API documentation, to avoid confusion.

Throwing Exceptions in Dart for Invalid Parameters (e.g. Sign In)?

I have an async function signIn in a Dart program that takes username and password string arguments. The function calls a remote server and the server responds with a session token or validation messages in the case of missing or incorrect username and/or password.
Currently I have this implemented with callbacks. The appropriate callback is called after the server responds. No need for await.
signIn(username, password, onSuccess, onFailure);
The more I read about Dart, I feel like the above isn't really the Dart way of doing things. Should I be using await combined with try and catch? Something like the following?
try {
sessionToken = await signIn(username, password);
// navigate from the sign in screen to the home screen.
} on InvalidParams catch (e) {
// e contains the server's validation messages
// show them to the user.
}
Invalid sign in credentials are likely. Handling them is normal program flow. I was taught never to use try/catch for regular, expected program flow. It seems that the Dart language is encouraging using exception handling for this especially in combination with await.
From Error class documentation [Emphasis mine.]
If the conditions are not detectable before calling a function, the
called function should not throw an Error. It may still throw a value,
but the caller will have to catch the thrown value, effectively making
it an alternative result rather than an error. The thrown object can
choose to implement Exception to document that it represents an
exceptional, but not erroneous, occurrence, but it has no other effect
than documentation.
What's the best most Dart way to implement this?
Error vs. Exception
The documentation you linked essentially says that the Error class should not be used for what you define as "regular, expected program flow" but Exception should. This also means that using try-catch for addressing these kinds of cases is encouraged in Dart.
From the documentation, Error's should be used for "a program failure that the programmer should have avoided", i.e. unexpected program flow. However, Exception's are "intended to convey information to the user about a failure, so that the error can be addressed programmatically", i.e. expected program flow.
In order to implement exceptions, you will have to extend Exception and create your own exception class. Dart enforces this by not providing access to the message passed to a regular Exception.
Creating instances of Exception directly with new Exception("message") is discouraged, and only included as a temporary measure during development, until the actual exceptions used by a library are done.
Example
enum InvalidCredentials { username, password }
class InvalidCredentialsException implements Exception {
final InvalidCredentials message;
const InvalidCredentialsException({this.message});
}
function() {
try {
await signIn(username, password);
} on InvalidCredentialsException catch (e) {
switch (e.message) {
case InvalidCredential.username:
// Handle invalid username.
break;
case InvalidCredential.password:
// Handle invalid password.
break;
}
} on Error catch (e) {
print(e);
} catch (e) {
// Handle all other exceptions.
}
}
I created InvalidCredentialsException to handle invalid credentials passed to signIn. For the message (you can call it whatever you want), I simply used an enum to distinguish between an invalid username and an invalid password (probably not what you would want to do, it should just explain the concept).
When handling it using try-catch, you can create different catch-blocks for different types. In my example, I use on InvalidCredentialsException for responding to the expected exception in your program flow and another one on Error for unexpected failures.
When using on for catch-statements, you run the risk of not catching other types of exceptions, which will then be thrown. If you want to prevent that, you can either have another block for generic exceptions, i.e. on Exception or just have a generic catch-block at the end (catch (e)).
You might want to override toString in your exception class if you want to be able to print out your exception.
Additionally, you can obviously transport as much information with your exception as you like, e.g. (modified from the above code):
// ...
throw InvalidCredentialsException(cause: InvalidCredentials.password, message: password);
// ...
class InvalidCredentialsException implements Exception {
final InvalidCredentials cause;
final String message;
const InvalidCredentialsException({this.cause, this.message});
}

How to do exception handling with nunit and moq?

I am trying to use nunits new way of exception handling but I am finding it hard to find information on it and how to also use it with moq.
I have right now moq that throws a exception on a mocked method but I don't know how to use nunit to catch it and look at it.
There's a few different ways to do it; I use Assert.Throws.
var exception = Assert.Throws<YourTypeOfException>(()=> Action goes here);
e.g.
var exception = Assert
.Throws<ArgumentNullException>(()=> new ChimpPuncher(null));
You can then query the exception object further if you want, e.g.
Assert.That(exception.Message, Text.Contains("paramname");
Best way to mention is: [ExpectedException(typeof(ApplicationException))] above the test method.
Why can't you enclose the mocked method call in a try/catch block and catch the specific exception being thrown?