| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'package:matcher/matcher.dart'; |
| |
| import '../utils.dart'; |
| import 'async_matcher.dart'; |
| import 'format_stack_trace.dart'; |
| |
| /// This function is deprecated. |
| /// |
| /// Use [throwsA] instead. We strongly recommend that you add assertions about |
| /// at least the type of the error, but you can write `throwsA(anything)` to |
| /// mimic the behavior of this matcher. |
| @Deprecated('Will be removed in 0.13.0') |
| const Matcher throws = Throws(); |
| |
| /// This can be used to match three kinds of objects: |
| /// |
| /// * A [Function] that throws an exception when called. The function cannot |
| /// take any arguments. If you want to test that a function expecting |
| /// arguments throws, wrap it in another zero-argument function that calls |
| /// the one you want to test. |
| /// |
| /// * A [Future] that completes with an exception. Note that this creates an |
| /// asynchronous expectation. The call to `expect()` that includes this will |
| /// return immediately and execution will continue. Later, when the future |
| /// completes, the actual expectation will run. |
| /// |
| /// * A [Function] that returns a [Future] that completes with an exception. |
| /// |
| /// In all three cases, when an exception is thrown, this will test that the |
| /// exception object matches [matcher]. If [matcher] is not an instance of |
| /// [Matcher], it will implicitly be treated as `equals(matcher)`. |
| Matcher throwsA(matcher) => Throws(wrapMatcher(matcher)); |
| |
| /// Use the [throwsA] function instead. |
| @Deprecated('Will be removed in 0.13.0') |
| class Throws extends AsyncMatcher { |
| final Matcher _matcher; |
| |
| const Throws([Matcher matcher]) : _matcher = matcher; |
| |
| // Avoid async/await so we synchronously fail if we match a synchronous |
| // function. |
| @override |
| dynamic /*FutureOr<String>*/ matchAsync(item) { |
| if (item is! Function && item is! Future) { |
| return 'was not a Function or Future'; |
| } |
| |
| if (item is Future) { |
| return item.then((value) => indent(prettyPrint(value), first: 'emitted '), |
| onError: _check); |
| } |
| |
| try { |
| var value = item(); |
| if (value is Future) { |
| return value.then( |
| (value) => indent(prettyPrint(value), |
| first: 'returned a Future that emitted '), |
| onError: _check); |
| } |
| |
| return indent(prettyPrint(value), first: 'returned '); |
| } catch (error, trace) { |
| return _check(error, trace); |
| } |
| } |
| |
| @override |
| Description describe(Description description) { |
| if (_matcher == null) { |
| return description.add('throws'); |
| } else { |
| return description.add('throws ').addDescriptionOf(_matcher); |
| } |
| } |
| |
| /// Verifies that [error] matches [_matcher] and returns a [String] |
| /// description of the failure if it doesn't. |
| String _check(error, StackTrace trace) { |
| if (_matcher == null) return null; |
| |
| var matchState = {}; |
| if (_matcher.matches(error, matchState)) return null; |
| |
| var result = _matcher |
| .describeMismatch(error, StringDescription(), matchState, false) |
| .toString(); |
| |
| var buffer = StringBuffer(); |
| buffer.writeln(indent(prettyPrint(error), first: 'threw ')); |
| if (trace != null) { |
| buffer |
| .writeln(indent(formatStackTrace(trace).toString(), first: 'stack ')); |
| } |
| if (result.isNotEmpty) buffer.writeln(indent(result, first: 'which ')); |
| return buffer.toString().trimRight(); |
| } |
| } |