noSuchMethod method
Invoked when a nonexistent method or property is accessed.
A dynamic member invocation can attempt to call a member which doesn't exist on the receiving object. Example:
dynamic object = 1;
object.add(42); // Statically allowed, run-time error
This invalid code will invoke the noSuchMethod
method
of the integer 1
with an Invocation representing the
.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod to provide custom behavior for such invalid dynamic invocations.
A class with a non-default noSuchMethod invocation can also omit implementations for members of its interface. Example:
class MockList<T> implements List<T> {
noSuchMethod(Invocation invocation) {
log(invocation);
super.noSuchMethod(invocation); // Will throw.
}
}
void main() {
MockList().add(42);
}
This code has no compile-time warnings or errors even though
the MockList
class has no concrete implementation of
any of the List
interface methods.
Calls to List
methods are forwarded to noSuchMethod
,
so this code will log
an invocation similar to
Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
it becomes the result of the original invocation.
If the value is not of a type that can be returned by the original
invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError.
Implementation
@override
dynamic noSuchMethod(Invocation invocation) {
invocation = _useMatchedInvocationIfSet(invocation);
if (_whenInProgress) {
_whenCall = _WhenCall(this, invocation);
return null;
} else if (_verificationInProgress) {
_verifyCalls.add(_VerifyCall(this, invocation));
return null;
} else if (_untilCalledInProgress) {
_untilCall = _UntilCall(this, invocation);
return null;
} else {
_realCalls.add(RealCall(this, invocation));
_invocationStreamController.add(invocation);
final cannedResponse = _responses.lastWhere(
(response) {
return response.call.matches(invocation, <dynamic, dynamic>{});
},
orElse: __defaultResponse,
);
return cannedResponse.response(invocation);
}
}