How do I test dart NoSuchMethodError - dart

How do i test for a class that some method doesn't exists NoSuchMethodError Exists?
something like the below example.
expect(1.leftShift(12), NoSuchMethodError);

You can test this like you would any other error. You can pass in a function that throws the error into expect and check that it throws the right error:
const dynamic x = 'hello';
expect(() => x.notAMethod(), throwsA(isA<NoSuchMethodError>()));
Note that you will need to make your receiver (the object you are calling the method on) to be dynamic to suppress the static error that would otherwise catch this error.

Related

dart: how to catch TypeError during compilation

Below code throws a runtime error.
TypeError: Instance of 'FormatException': type 'FormatException' is not a subtype of type 'CustomException'
Why Test(e) does not fail at compilation as type of e is Exception and expected is CustomException. How to enforce it so one cannot pass Exception there.
abstract class CustomException implements Exception {
String get code;
}
class Test {
final CustomException ex;
Test(this.ex);
}
void main() {
try {
throw new FormatException();
} on Exception catch (e) {
final t = Test(e);
print('message: $t');
}
}
Dart has (for now) implicit downcasts from a supertype to a subtype. You are allowed to use an expression which is a super-type of the actual type that is required, under the assumption that you know what you are doing.
Here you have a value with static type Exception (the e that was caught), and you pass it to a constructor requiring a CustomException, which is a subtype of Exception.
The language allows this, but inserts a run-time downcast (equivalent to e as CustomException). That cast fails because the value is actually a FormatException.
With the up-coming null safety feature, implicit downcasts will be removed except from dynamic (because dynamic turns off static type checks anyway). When that happens, the Test(e) invocation becomes invalid. Until then, this code compilers and fails at run-time.
Until then, you can get the analyzer to warn you about implicit calls by configuring it in the analysis_options.yaml file

Matching a method signature with a unknown parameter in a mocked class

I have this method:
Future<Either<Failure, WorkEntity>> updateWorkEntity({int id, String title, TimeType timeType, int times, DateTime executed})
that is being called like this:
repository.updateWorkEntity(id: workEntity.id, executed: DateTime.now())
the id I can control in a test, but the "DateTime.now()" I ofcourse can not. What I tried was this in my test:
when(repository.updateWorkEntity(id: expected.id, executed: any)).thenAnswer((_) async => Right(expected));
to be able to make my mock return a object for my test, by using "any" in the place of the "DateTime.now()", but I get this error:
Invalid argument(s): The "any" argument matcher is used outside of
method stubbing (via when) or verification (via verify or
untilCalled). This is invalid, and results in bad behavior during
the next stubbing or verification.
So I guess I can not use any here, but then how do I get my mock to return an object when I do not control one of the input parameters?
Thank you
Søren
Use executed: anyNamed('executed') instead of executed: any

How to call a JavaScript function named `call` from dart

Is there any way to call a JavaScript function named call() (in a nested object) from Dart or do I have to wait for Dart 2.0 from which the special handling of call() might get removed?
I have a JS Proxy like:
#JS()
class SomethingFancy {
external String call();
}
But as call() can be used to turn an object into a function, it makes it impossible to access the function of the JS object.
If I could, I would change the name of the method in Dart, but that's not supported by package:js:
/// By default the dart name is used. It is not valid to specify a custom
/// [name] for class instance members.
The error I get is:
Uncaught Error: NoSuchMethodError: method not found: 'call$0' (J.getSomethingFancy$1$x(...).call$0 is not a function)
If the function didn't exist, the error would look like this:
Uncaught Error: NoSuchMethodError: method not found: 'callMe' (receiver.callMe is not a function)
Other functions on the same object work just fine.
You can prefix call with JS$:
#JS()
class SomethingFancy {
external String JS$call();
}
JS$ can be used as prefix to allow to access to JS names that conflicts with dart keywords.

Using dart:web_audio

I have some confusion debugging some simple app that uses the Web Audio API.
In the developer console I can do something like this:
var ctx = new webkitAudioContext(),
osc = ctx.createOscillator();
osc.connect(ctx.destination);
osc.start(0);
Trying to get this to work with Dart yields the following errors when I try it like this:
AudioContext ctx = new AudioContext();
OscillatorNode osc = ctx.createOscillator();
osc.connect(ctx.destination);
osc.start(0);
//Dart2JS: Uncaught TypeError: Object #<OscillatorNode> has no method 'connect$1'
//DartVM: Class 'OscillatorNode' has no instance method 'connect' with matching
arguments. NoSuchMethodError: incorrect number of arguments passed to method
named connect' Receiver: Instance of 'OscillatorNode'
Stepping through I found that there are two kinds of implementations to the connect method. So I tried to add an extra second param and since I can not really wrap my head around why it needs an int named "output", thinking maybe it is for volume I decided on the value 1 but that yields:
//Dart2JS: Uncaught Error: IndexSizeError: DOM Exception 1 flexsynth.html_bootstrap.dart.js:8698 $.main flexsynth.html_bootstrap.dart.js:8698 $$._IsolateContext.eval$1flexsynth.html_bootstrap.dart.js:565 $.startRootIsolate flexsynth.html_bootstrap.dart.js:7181 (anonymous function)
//DartVM: "Dart_IntegerToInt64 expects argument 'integer' to be non-null."
Here is where I can't figure out what to do, I think the argument is not null, it is 1.
Googling the errors only leads me to the actual Dart source code.
Is there any place that explains how to work with the dart:web_audio? What am I doing wrong?
This is because the underlying implementation seems to require the parameter input, despite it being an optional parameter. This code will work:
AudioContext ctx = new AudioContext();
OscillatorNode osc = ctx.createOscillator();
osc.connect(ctx.destination, 0, 0);
osc.start(0);
This is a known bug, you can star it here: https://code.google.com/p/dart/issues/detail?id=6728

Asserting return type of MVC Controller Action

How can you assert that an expected type is returned when it is wrapped up in a System.RuntimeType?
As part of a larger unit test to verify that an action has the correct parameters and action filters assigned I'm asserting against a populated instance of MethodInfo. When I assert against "action.ReturnParameter" it fails as it's saying the type is System.RunTimeType. Whilst I understand that this is a wrapper around the expected type, I just can't seem to find a way to assert that the wrapped instance is of the expected type - the best method that I've come up with so far is to assert against name or full name, but that's horrible as it's just using "magic strings".
Can anyone help? As my Google searches haven't turned up anything useful, I'm guessing it's got a really easy solution, I'm just not seeing it.
The code is as follows:
[TestMethod]
public void CheckActionFilterSet()
{
MethodInfo action = new CustomerController((new MockHttpContext()).Object)
.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(mi => mi.Name.Equals("Search")).First();
Assert.That(action.ReturnParameter.ParameterType, Is.InstanceOf(typeof(ViewResult)), "View Result should be of expected type");
}
Exception message is:
View Result should be of expected type
Expected: instance of
<System.Web.Mvc.ViewResult>
But was:
<System.RuntimeType>
Just call the controller method and check the type of the object that is returned:
var result = new CustomerController((new MockHttpContext()).Object).Search(....);
Assert.That(result, Is.InstanceOf(typeof(ViewResult)), "View Result should be of expected type");
You can also check the values of ViewData / model if you want to...

Resources