New to Dart and currently learning about null safety.
I've been trying to make a neat simple program with proper null handling while taking input from user (stdin.readLineSync) but I can't seem to get it right.
I've read about nullables and how it can be handled using exceptions. Here, I'm simply trying to take an input from user and store it as an integer.
import 'dart:io';
void main() {
int? nmr;
print('input text to parse:');
String? txt = stdin.readLineSync();
if(txt == null){
throw Exception('field can not be empty!');
} else {
nmr = int.tryParse(txt);
if (nmr == null) {
throw Exception('invalid input!');
} else {
print(nmr);
}
}
}
It run without error, except that when I don't input anything as the txt (txt == null), the console threw the 'invalid input!' instead of the 'field can not be empty' which I was expecting. Where and how did I do wrong? I think perhaps I misunderstood about how the nulls and exceptions work somehow. Thanks.
Related
I am asking for a user input, and it has to be a String and not null afterall.
Can somehow an user enter a non string value or null? so I would be force to validate it?
or I can safely skip this validation code? (since it is redundat)
String? userInput = stdin.readLineSync();
if (userInput != null){
if (userInput.runtimeType == String){
print('Validated input');
} else{ // if is not a string
print('You did not entered a string');
}
print('You entered a null value'); // if null
}
First, you should, in general, not use .runtimeType in production code. E.g. in your example it would be better to use if (userInput is String) to test if userInput are compatible with the String type. The difference is that we often don't care about exact types but rather if something is just compatible with a given type.
Next, the stdin.readLineSync() is defined to return String? which means it is enforced by the type system to return a String or null. It can't return e.g. a number.
So your if (userInput != null) is actually enough since if this is the case, we know for a fact that userInput must then be a String.
import 'dart:io';
void main() {
String? userInput = stdin.readLineSync();
if (userInput != null){
print('Validated input. Input must be a String.');
} else {
print('You entered a null value by closing the input stream!');
}
}
For when userInput can become null, it happens if the user are closing stdin input stream. You can do that in bash (and in other terminals) by using Ctrl+D keyboard shortcut. If doing so, the userInput would become null.
I'm using mapstruct in my project, and recently went to add some 'mutation analysis' using pitest.
The problem I have is that a mutant is created on some generated code, and I cannot fix my test to kill it since this is concerning null check generated by mapstruct, that are unreacheable.
ie, if I have the following mapper :
#Mapper
public abstract class MyMapper {
#Mapping(source= "someInnerObject.field", target="someField")
public abstract Bar toBar(Foo foo);
}
Mapstruck will generate something like this :
public class MyMapperImpl extends MyMapper {
#Override
public Bar toBar(Foo foo) {
if(foo == null) {
return null; // reacheable code, all is fine here.
}
Bar bar = new Bar();
bar.setSomeField(fooSomeField(foo))
return bar;
}
private String fooSomeField(Foo foo) {
if (foo == null) {
return null; // Unreacheable code, already tested in public method.
}
SomeInnerObject innerObject = foo.getSomeInnerObject()
if(innerObject == null) {
return null; // reacheable code, no problem here
}
String field = o.getField();
if(field == null) {
return null; // reacheable, no problem here.
}
return field;
}
}
As we can see, mapstruct generates a null check that is unreacheable, making it impossible to cover those line in test. The mutation analyser tries to return "" instead of null on the unreacheable line, and therefore, the mutant is never detected by my tests. This leads makes it impossible to get 100% code coverage and 100% mutation coverage.
I don't think excluding this generated code from the coverage or the mutation analysis would be a good choice, since the generated code reflect behavior that is coded as annotations in the mapper : So we would like to make sure these behaviors are correctly covered in tests.
Do someone here had the same problem, or any suggestion ?
I tried many different mapper config to get rid of the unreacheable line without success (unless I just disable all null checks, which would change my application logic).
The way MapStruct generates code doesn't allow us to skip the null check in the private method.
You can try raising an issue in the MapStruct project. However, I am not sure that it is worth spending time on skipping this null check. The JIT will in any case remove that check during runtime.
The topic about 100% code coverage and 100% mutation coverage is a topic for discussion that will lead to closing this question.
I was trying to parse the return of an IronAjax success handler and set the response to an instance of Map. It seems to not like that.
My HTML Markup is:
<iron-ajax id="myAjaxId" auto
url="http://localhost:12345/test_server/v1/daily"
handle-as="json"
on-response="handleResponse" on-error="handleError"></iron-ajax>
My Dart Code is:
void handleResponse(CustomEventWrapper cew, IronRequest ir){
print("inside handleResponse");
var data = ir.response; // <-- is type JsObjectImpl
print("data");
print(data);
if (data == null) return;
print ("About to set rows");
List<Map> rows = data.containsKey("data") ? data["data"] : [];
print("Variables are Set locally");
$['myDatagrid'].render();
}
#reflectable
String camelToFormal (String input){
String out;
RegExp regex = new RegExp("([A-Z])");
out = input[0].toUpperCase() + input.substring(1).replaceAllMapped(regex, (Match m) => " ${m[1]}");
return out;
}
#reflectable
void handleError(CustomEventWrapper cew, IronRequest ir){
print("____Error:____");
print(ir.response);
}
The Error I get is:
type 'JsObjectImpl' is not a subtype of type 'Map' of 'other'.
I wasnt sure if I need to run convert over it, even though the return type set by IronAjax was json
So, since ir.response will either be set or null, i check if it is null first. the var data line in responseHandler currently sets is, but i have also attempted to do something like: Map data = new Map.from(ir.response); which fails as well.
Even though this is said to be handled as JSON, and is returning a jslint confirmed objected, it seems to have issues to convert it to a proper map instance.
According to Polymer IronRequest at: https://elements.polymer-project.org/elements/iron-ajax?active=iron-request
it says that responseis *, the parsed response body. Am I mistaken as to how this is properly set up, or am I missing something?
You could try Object instead of map on the property and then use convertToDart. Not sure this results in a Map but worth a try I guess. See also Polymer 1.0 - iron-list - selection
I am using MVC3, C#, Razor, .NET4
I use a session variable in my Model constructor. Sometimes it can be null, mainly due to recycling of the AppPool. I need to catch the "null" error of the session and ideally redirect to another action ie Error/Index. However I am in model, and I am not sure whether one can redirect out of a model class.
my Code:
try
{
intOrderId = (Int32) System.Web.HttpContext.Current.Session["OrderId"];
intSupplierId = (Int32) System.Web.HttpContext.Current.Session["SupplierId"];
}
catch (Exception e)
{
// Redirect to Error/Index ?????
}
I have a feeling that I may have to set a property in the model to highlight the error, and then have the controller's action inspect this and act accordingly, howowever I have loads of actions that call this model, so I am not wanting to do this. I would rather react to this error in one place.
Many thanks in advance for any help on this.
Rather than using try/catch to handle empty values, why not check before you read?
if(System.Web.HttpContext.Current.Session["OrderId"] != null)
&& System.Web.HttpContext.Current.Session["SupplierId"] != null)
{
intOrderId = (Int32) System.Web.HttpContext.Current.Session["OrderId"];
intSupplierId = (Int32) System.Web.HttpContext.Current.Session["SupplierId"];
}
else
{
//Throw an exception that the controller can catch: NullReferenceException or InvalidCastException.
//Or return a specific value to indicate that an error occured
}
Does anyone have a simple way of handling this exception when updating a record to one that already exists in the database?
Try this:
catch (UpdateException ex)
{
SqlException innerException = ex.InnerException as SqlException;
if (innerException != null && innerException.Number == ??????)
{
//Place you exception code handling here..
}
else
{
throw; //(bubble up)
}
}
This is a simple solution, but you may have issues in the future should the error number change which is unlikely).