Coder Social home page Coder Social logo

mockito's Issues

please add method docs for typed, not just in the README

The README identifies a few situations in which you might want to use typed,
but nothing currently explains what typed actually is/does.
Please add method docs.

In particular, it seems to me that its purpose in life is to claim to strong mode that it returns whatever
type the call site demands (which of course can only happen if it always returns null... which it does). And the reason we'd want that is basically to tell strong mode to shut up.
It's as if its name really should have been inferTypeFromUsage, although that would be much too long.

.captured sometimes returns strange closures

I have this calls:

VerificationResult result = verify(transaction.queueMutations(inserts: captureThat(isList)));
print(result.callCount);
print(result.captured.length);
result.captured.forEach(print);

and the output is:

6
9
Closure: (Transaction) => dynamic
Closure: (Transaction) => dynamic
Closure: (Transaction) => dynamic
[Transaction.69140b7c-742f-469f-b039-303af8390c67]
[Instance of 'User']
[Transaction.69140b7c-742f-469f-b039-303af8390c67]
[Instance of 'User']
[Transaction.69140b7c-742f-469f-b039-303af8390c67]
[Instance of 'User']

First of all: it seems very strange that captured calls for captureThat(isList) would return closures.
Then it seems strange that the .callCount differs from .captured.length.
And lastly: where do those Closures come from?

I haven't found any better way to debug this, but maybe you could guide me in the right direction to get to the bottom of this.

Thanks

EDIT: For the record: the last 6 entities in the result.captured list are the expected values.

Mockito needs significantly more documentation

The dartdocs for mockito leave much to be desired.

Here are some random examples:

  • when has no docs and the library itself has no top-level docs (as far as I can tell these are the two most important things in mockito).

  • One of the first things in the README is:

    Let's verify some behaviour!

    //using mock object
    cat.sound();
    //verify interaction
    verify(cat.sound());

    Once created, mock will remember all interactions. Then you can selectively verify whatever interaction you are interested in.

    I have no idea what any of that means. The word "verify" is never defined. The dartdocs for verify are blank.

  • The README references throwOnMissingStub in a code sample with no prose. That method doesn't seem to exist.

  • The word "answer" appears exactly once in the README, with no commentary, and there's no dartdocs for either PostExpectation.thenAnswer or Answering.

Enable travis builds

I've got the scripts in flight (#9) but the repo needs to be enabled. Apparently, this can only done by the repo owner, so it's on you @fibulwinter :)

To do it, visit https://travis-ci.org/ and you should find a slider for dart-mockito. Flick the repository switch on and we should be good to go.

Mockito 2.2.0 is stricter in a few, undocumented ways.

In upgrading a large corpus of tests to Mockito 2.2.0, I've found a few undocumented new restrictions. I think it would be good to document them:

  • captureAny args used to be captured when captureAny was used in when, and that functionality has disappeared. It wasn't explicitly supported before, but I'd still like this change documented.

  • matching used to be looser when not using argThat(equals(...)). For example:

    import 'package:mockito/mockito.dart';
    import 'package:test/test.dart';
    
    class MockedClass extends Mock implements RealClass {}
    
    class RealClass {
      String methodWithListArgs(Iterable<int> x) => "Real"
    }
    
    void main() {
      test("should mock method with List args", () {
        when(mock.methodWithListArgs([42])).thenReturn("Ultimate answer");
        var ary = [42].map((e) => e * 2 / 2); // ary is an Iterable that looks like [42].
        expect(mock.methodWithListArgs(ary), equals("Ultimate answer"));
      }
    }

    fails. It did not used to. expect(mock.methodWithListArgs(argThat(equals(ary))), ... works though.

  • stubs that return Future are behaving weird for me... have not pinned down yet.

Make PostExpectation generic.

An error cropping up while migrating tests to Dart 2.0 semantics is having invalid return types for thenAnswer which cause runtime issues.
For example consider the class Foo:

class Foo {
    Future<B> doSomething(A a);
}

Set up the mock for Foo as follows:

MockFoo foo = new MockFoo()
when(foo.doSomething(any(a)).thenAnswer((_) => new B())

The above will currently run without issue in the VM. However, the return type of thenAnswer is invalid as it should be returning Future<B> instead of the raw B value. I believe we can catch these errors through analysis. when uses PostExpectation which can be made generic. This will allow us to enforce the return type of thenAnswer accordingly.

Handle method tear-off on mock

It would be great to be able to have

    test("should verify tear-off", () {
      final f = mock.methodWithoutArgs;
      f();
      verify(mock.methodWithoutArgs());
    });

Use-case

I was refactoring some code from

for (var i in list)
  o.m(i);

to

list.foreach(o.m);

This change triggers several test failures:

  NoSuchMethodError: The method 'call' was called on null.
  Receiver: null
  Tried calling: call()

Mock methods

I have this example code:

class FooExample {

  int calculate() {
    return myCalc();
  }

  int myCalc() {
    return 6 * 7;
  }
}

And I have following test code:

import 'package:test/test.dart';
import 'package:mockito/mockito.dart';

class MockFooExample extends Mock implements FooExample { }

void main() {

  FooExample ft = spy(new MockFooExample(), new FooExample());

  test('calculate', () {
    when(ft.myCalc()).thenReturn(10);
    expect(ft.myCalc(), 10);
    expect(ft.calculate(), 10);
  });
}

I was expecting the last expect call to return 10, when calling ft.calculate(), but it still return 42.
Am I missing something?

Friendly debug messages when mock methods without expectations set are called.

For example:

//Real class
class Cat {
  String sound() => "Meow";
}

//Mock class
class MockCat extends Mock implements Cat {}

//mock creation
var mockCat = new MockCat();

// Would throw exception "NoSuchMethodError: The method 'toUpperCase' was called on null.".
mockCat.sound().toUpperCase();

The actual cause is during the test development, developer forgot to write "when(cat.sound()).thenReturn("Purr");".

The message "'toUpperCase' was called on null" isn't helpful for finding out the casue and a more friendly message could be "'toUpperCase' was called on the return value of 'Cat.sound()', but no exceptions were set on it".

This could be achieved by returning instead of 'null' but a special object carrying the method invocation information for any 'un-expected' methods.

I can come with a design doc if this sounds possible.

Add capturedAs<T>() helper?

Not high priority, but the unfortunate fact that captured is a List<dynamic> does not play well with the Dart 2 concept of not-using-dynamic-as-bottom. For example:

cat.eatFood("Milk");
cat.eatFood("Fish");
expect(
    verify(cat.eatFood(captureAny)).captured.every((String s) => s.isNotEmpty), isTrue);

This code treats dynamic as bottom, by passing a Function(String) where a Function(dynamic) is expected. In Dart 2 you have cast<T>() and retype<T>() at your fingertips, so you can do:

expect(
    verify(cat.eatFood(captureAny))
        .captured
        .retype<String>()
        .every((String s) => s.isNotEmpty),
    isTrue);

which (again, not high priority) either adds a few characters to your statement, or a new line (or forces line wrapping). We could provide capturedAs<T>():

expect(
    verify(cat.eatFood(captureAny))
        .capturedAs<String>()
        .every((String s) => s.isNotEmpty),
    isTrue);

One problem is how do you treat function invocations with multiple captured arguments...

add thenThrow to API

This can be done now with thenAnswer, but it's nice for the API (Both Dart's package:mock and Java's mockito have a thenThrow).

Flip mockito.dart with mockito_no_mirrors.dart

I think it would be worth it just to have package:mockito/mockito.dart not include mirrors.

The only extra function Mockito provides for mirrors users is spy:

dynamic spy(dynamic mock, dynamic spiedObject) {
  var mirror = reflect(spiedObject);
  setDefaultResponse(
      mock,
      () => new CannedResponse(null,
          (Invocation realInvocation) => mirror.delegate(realInvocation)));
  return mock;
}

I am not even sure there is usage of this and could be convinced to just remove it.

/cc @srawlins @TedSander

Discuss: "No matching calls" when verify() calls should diff...

if there is an equivalent call with non-matching parameters. For example, instead of

No matching calls. All calls: MyService.update(div, {bottom: 5})

Perhaps

No matching calls.

FOUND: MyService.update(div, {bottom: 5})
EXPECTED: MyService.update(div, {bottom: 4})
DIFF:
  bottom was 4 instead of 5

(I'd be happy to help write this, just wanted input first)

@TedSander

Migrate syntax to be 2.0-primary

Today a user can write when(cat.eatFood(any))...;, in Dart 1. This has always been odd because eatFood accepts a String, not an ArgMatcher (the return value of any). But Dart 1 was okie dokie with this, and it allowed for a great mocking library. Dart 2 is not ok with this, hence the Strong Mode compliance API. We should switch mockito to ultimately only support the Dart 2 type system, i.e. make when(cat.eatFood(any))...; look like today's when(cat.eatFood(typed(any)))...;.

This is absolutely a breaking change, and will be the primary feature that bumps us to Mockito 3.0. It also prevents some old mocking behavior:

when(obj.fn(any, null)) will no longer be allowed (null in arg list with any), as mentioned in the strong mode compliance docs. We'll require when(obj.fn(any, argThat(equals(null))). I think we can introduce nullArg or something...

We can also keep typed around as an identity function, to allow users to migrate gracefully (except the case above).

Mock functions?

Don't really know how or if this is achievable but it would be great if there's some magical means to create a mock function rather than a mock class that can be passed into things expecting any sort of typedefs or function signatures and then verify its (dynamic) calls and args.

Having a class use a mocked version of another one

While learning about flutter testing and trying to write tests for my small application, I couldn't figure out how to mock a class used by another one.

Considering a stateful widget ListScreen and its related ListScreenState, the build methods returns an AppBar with a localized text.

When trying to write a test for this widget

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';

import 'package:grablunch/list.dart' show ListScreen;
import 'package:grablunch/localization.dart' show AppLocalizations;

class MockAppLocalizations extends Mock implements AppLocalizations {}

void main() {
  var localizations = new MockAppLocalizations();
  when(localizations.titleList).thenReturn("titleList");

  testWidgets('my first widget test', (WidgetTester tester) async {
    await tester.pumpWidget(
      new StatefulBuilder(
        builder: (BuildContext context, StateSetter setState) {
          return new ListScreen();
        },
      ),
    );
  });
}

flutter test will fail as follow:

โžœ flutter test test/widget_test.dart
00:00 +0: - my first widget test
โ•โ•โ•ก EXCEPTION CAUGHT BY WIDGETS LIBRARY โ•žโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
The following NoSuchMethodError was thrown building ListScreen(dirty, state: ListScreenState#496f0):
The getter 'titleList' was called on null.
Receiver: null
Tried calling: titleList

Makes sense since the translation is called out of AppLocalizations.of(context).titleList), and the locales were defined in the root widget, not used for this test (trying to make a widget test, not an integration one).

How would you go about mocking AppLocalizations (or the context) on the ListScreen class?
I tried

var testListScreen = new ListScreen();
testListScreen.context = new Mock();

and to return testListScreen instead, but the context not having a setter, I failed to suceed this way.

Kind of tough to figure things out, lacking some debugging foo up my sleeves. To be honest, I'm not even sure how to test this kind of app that heavily relies on external packages like the firebase ones.
Thanks for your help

Add information on how it works

Mockito looks great, but it would be nice if you could add information in the README (or wiki) on how it works.

For example:

// unstubbed methods return null
expect(cat.sound(), nullValue);
// So I'm assuming here that cat.sound() returns `null`

// stubbing - before execution
when(cat.sound()).thenReturn("Purr");
// How does `cat` get configured here? If `cat.sound()` returns
// `null`, I don't see how `when` is able to modify `cat`s behaviour

I can of course (and will) go through the code, to get this information, but it would be nice to have a paragraph about the internals.

argThat(...) doesn't work in stricter strong mode

... i.e. implicit-casts: false and implicit-dynamic: false.

/// An argument matcher that matches an argument that matches [matcher].
argThat(Matcher matcher) => new ArgMatcher(matcher, false);

But typed expects a ArgMatcher. The above returns dynamic.

Is this fixable? Or should we just basically wait for a future codegen-based mockito?

Make Mock.realCalls private

This will eliminate any chance of collision with other APIs (a huge issue with mock). You can add a public function to retrieve the value if needed.

More Maintainers

I'm not sure how to give you this message otherwise, but I would be happy to help you maintain this if you are looking for someone to help.

Need a 2.3.0 release with same-semantic wrappers for easy migration to Mockito 3

Today, the ergonomic any can be used in named arguments, but this won't be allowed in Mockito 3.0. Additionally, to use Mockito with DDC ("Dart 2 semantics"), we provide the typed API, that provides an optional named argument.

// MOCKITO 2.x API

// Plain `argThat` and `any` API.
when(mockObj.fn(argThat(contains('text')), foo: any)).thenReturn(0);

// A test run with DDC that could not pass ArgMatcher arguments at runtime.
when(mockObj.fn(typed(any), foo: typed(any, named: 'foo'))).thenReturn(0);

Both of these examples are incompatible with the proposed syntax for Mockito 3.0 (#85), even though we leave typed around for backwards compatibility purposes. They would need to be migrated to:

// MOCKITO 3.X API
// Bare `any` calls are no longer allowed in named arguments.
when(mockObj.fn(argThat(contains('text')), foo: anyNamed('foo'))).thenReturn(0);

// `typed` made available for backward-compatibility...
when(mockObj.fn(typed(any), foo: anyNamed('foo'))).thenReturn(0);
// ... but could be removed: it's the identity function in Mockito 3.0.
when(mockObj.fn(any, foo: anyNamed('foo'))).thenReturn(0);

We should provide a release with forwards-and-backwards-compatible API:

anyNamed(String named) => typed(any, named: named);
captureAnyNamed(String named) => typed(captureAny, named: named);
captureThat(Matcher matcher, {String named}) =>typed(captureThat(matcher), named: named);

With this API, the code could be moved to the MOCKITO 3.X API, and work in both Mockito 2.3+ and Mockito 3.0.

This transition implementation would be replaced with the release of Mockito 3.0:

Null anyNamed(String named) => _registerMatcher(anything, false, named: named);
Null captureAnyNamed(String named) =>
    _registerMatcher(anything, true, named: named);
Null captureThat(Matcher matcher, {String named}) =>
    _registerMatcher(matcher, true, named: named);

Offer an easy way to ignore named parameters

Consider

void a(String b, {String c, String d})

If it was actually invoked with a('b', c: null) or a('b', c: null, d: null) and I only care about 'b', there's no easy way to match that without manually going through every permutation.

typed() doesn't work well with named parameters

In order to transition to strong mode, we have been converting our when() and verify() calls from
any and captureAny to typed(any) and typed(captureAny)

However this doesn't work well with named parameters where

when(... foo: any) becomes when(... foo: typed(any, named: 'foo'))

Why does typed need to know the name of the parameter?
And the tests will break when the name of the parameter is refactored, which runs counter to one of the main advantages of Mockito compared to other mocking frameworks.

Captures use global vars, causing cross-talk between tests. Need a tearDown function

See the following repro: captures are not hermetic across tests, even though I'm using different mock instances between tests!!!

import 'package:mockito/mockito.dart';
import 'package:test/test.dart';

class Foo {
  foo(x) {}
}
class MockFoo extends Mock implements Foo {}

main() {
  MockFoo foo;
  setUp(() {
    foo = new MockFoo();
    when(foo.foo(captureAny)).thenAnswer((i) => null);
  });

  test('calls', () {
    foo.foo(1);
  });
  test('calls but gets all tests\' captures!', () {
    foo.foo(2);
    expect(verify(foo.foo(any)).captured, [1, 2]);
  });
}

Note that some things do seem to reset captures:

  • the (advertised as testing-only) function resetMockitoState, which we'll be using as a temporary workaround.

  • Any test which call to verify fails to match any invocation:

    test('does not call', () {
      expect(() => verify(foo.foo(any)), throws);
    });

We'd really need something like:

  tearDown(() => mockitoTearDown());

(hit the bug with some real-life tests)

New Dart 2 semantics Mockito API

We need to bump Mockito to be Dart 2-only, so that we can remove the pesky typed wrapper, so that everything is just any, argThat, captureArg, etc.

However, the new Mockito API will kind of have to adhere to the typed shortcoming of having to name named arguments by name, i.e. fn(argThat(equals(3), number: argThat(equals(7), named: 'number')). Boooo. Alas, this is unavoidable until we go to a code-genned Mockito, which is a bigger migration than this, and is not necessary until non-nullable types.

Which leads us to: how do we call any and captureAny, which are getters today, and have such marvelous ergonomics, when used with a named argument? ๐Ÿ˜ฆ Getters cannot take arguments.

Option A: We split the methods

Null get any => ...
Null anyNamed(String named) => ...
Null get captureAny => ...
Null captureAnyNamed(String named) => ...

This adds confusion because now named is a positional arg in anyNamed and captureAnyNamed, but a named arg in argThat and captureThat. ๐Ÿ˜ฆ (Option A2 can be where anyNamed and captureAnyNamed use a named argument for named.)

Option B: we force any to no longer be a getter, ever ๐Ÿ˜ฆ :

Null any({String named}) => ...
Null captureAny({String named}) => ...

This would mean using fn(any(), any(), any()) everywhere. Worse ergonomics, and really confusing and frustrating for people during migration.

Option C: Ugh, we go to codegen now

I don't want to do this. It will be huge migration, make Mockito harder to use where codegenning isn't super easy and streamlined, take longer, ... But it does remove the need to use named everywhere.

Emulating tearoffs hack doesn't work under Dart 2 semantics

This example is inspired from the comment on the Mock class:

// Real class.
class Cat {
  String getSound(String suffix) => 'Meow$suffix';
}

// Mock class.
class MockCat extends Mock implements Cat {}

void main() {
  // Create a new mocked Cat at runtime.
  var cat = new MockCat();

  // When 'getSound' is called, return 'Woof'
  when(cat.getSound).thenReturn('Woof');   // <-----

  // Try making a Cat sound...
  print(cat.getSound('foo')); // Prints 'Woof'
}

The indicated line is a little magical. In Dart 1 semantics, the evaluation of cat.getSound tries to call a non-existent getter against cat and winds up in Mock.noSuchMethod. Mock uses this point to store a closure in the _whenCall global which records the method name and arguments.

However, under Dart 2 semantics, since getSound(String _) is part of the interface for MockCat, a forwarder function for getSound is created, which will call Mock.noSuchMethod when invoked. Evaluation of cat.getSound now creates a tearoff of this forwarder. Mock.noSuchMethod isn't called, and the Mock class doesn't get a chance observe the method name and arguments.

Add async return helper

A lot of testing involves async code and it would be super convenient if you didn't have to create wrapper futures all the time but could instead delegate that to a thenReturnAsync method.
It would basically just be this in PostExpectation

  thenReturnAsync(expected) {
    return _completeWhen((_) => new Future.value(expected));
  }

I can submit a pull request if this sounds reasonable.

Discussion: returns stub instead of null for first class citizen member function

Hi,

In dart, member function can be used as first class citizen to simplify the code. Considering following code

void willCallCallback(void callback()) {
   ... do something
   callback();
}
abstract class HasFoo { void foo(); }
functionNeedToBeTested(HasFoo hasFoo) {
   ... do something
   return () { 
      ... do something
      willCallCallback(hasFoo.foo);
   };
}

I want to test the functionNeedToBeTested, but I can not simply write it as

var mockHasFoo = ...
var block = functionNeedToBeTested(mockHasFoo);
block();
verify(mockHasFoo.foo());

A full example:

typedef void UnaryFunction();

class HasCallback {
  final UnaryFunction _fooCallback;
  final UnaryFunction _barCallback;

  HasCallback(this._fooCallback, this._barCallback);

  void foo() {
    // Do something
    _fooCallback();
  }

  void bar() {
    // Do something
    _barCallback();
  }
}

class FunctionProvider {
  void abc() {
    print('abc is called');
  }
  void xyz() {
    print('xyz is called');
  }
}

HasCallback toBeTested(FunctionProvider funcProvider) {
  // Do something
  return new HasCallback(funcProvider.abc, funcProvider.xyz);
}

class UnaryFunctionClass {
  void call() {}
}

class MockFunctionProvider extends Mock implements FunctionProvider {}

class MockUnaryFunctionClass extends Mock implements UnaryFunctionClass {}

void main() {
  tearDown(() {
    // In some of the tests that expect an Error to be thrown, Mockito's
    // global state can become invalid. Reset it.
    resetMockitoState();
  });

  test('obj.foo is not equal to obj.foo()', () {
    var funcProvider = new MockFunctionProvider();
    expect(funcProvider.foo, null);
    verify(funcProvider.foo);

    funcProvider.foo();
    verify(funcProvider.foo());
  });

  test('using obj.foo as first class citizen is not possible now', () {
    expectFail('The method \'call\' was called on null', () {
      try {
        var funcProvider = new MockFunctionProvider();
        var hasCallback = toBeTested(funcProvider);
        hasCallback.foo();
        verify(funcProvider.abc());
        hasCallback.bar();
        verify(funcProvider.xyz());
      } catch (_) {
        throw new TestFailure('The method \'call\' was called on null');
      }
    });
  });

  test('to test member function as fisrt class citizen, '
      'need to write more code',
      () {
    var funcProvider = new MockFunctionProvider();
    var abc = new MockUnaryFunctionClass();
    var xyz = new MockUnaryFunctionClass();
    when(funcProvider.abc).thenReturn(abc);
    when(funcProvider.xyz).thenReturn(xyz);
    var hasCallback = toBeTested(funcProvider);
    hasCallback.foo();
    verify(abc.call());
    hasCallback.bar();
    verify(xyz.call());
  });
}

So for member function foo(), if it is called as mockObj.foo (and no when for it), can we return a stub instead of null, so that the test could be easier.

Thanks

Mockito without mirrors?

Would it be possible to create a version of mockito that doesn't use dart:mirrors? That would enable mockito to be used in environments that disable the mirrors support.

verify(someMethod).called(0) fails with unintuitive error.

I initially thought that verify(something).called(0) would be equivalent to verifyNever. Instead the first fails with a no matching calls error. I am not sure if this is a bug or not, but if called doesn't support values <= 0 then it should throw a better error, perhaps pointing a user to verifyNever.

Minimal example:

import 'package:test/test.dart';
import 'package:mockito/mockito.dart';

void main() {
  group('verify calls', () {
    test('verifyNever passes', () {
      var cat = new MockCat();

      verifyNever(cat.countLives());
    });

    test('verify .called(0) fails', () {
      var cat = new MockCat();

      verify(cat.countLives()).called(0);
    });
  });
}


class Cat {
  int countLives() => 9;
}

class MockCat extends Mock implements Cat {}

Publish latest to pub ? (to include updated README)

Hi,

Would it be possible to publish the latest version of this to pub.dartlang.org? Specifically, the README displayed on pub.dartlang.org doesn't include the hint to add nSM to your class so you can silence the analyzer warnings.

However, the latest version of the README does have that very useful hint.

Thanks!

Push users to .thenAnswer(<Future|Stream>)?

This is what I see a lot:

var mockThing = new MockThing();
when(mock.isDone).thenReturn(new Future.value(true));

// ...
runTest(thing: mockThing);

But it can break in basically un-debuggable ways, especially around zones. Normally a Future or Stream won't be created until an invocation is made, but with the .thenReturn pattern, it has been created in the test setup.

The "correct" behavior here would be to use .thenAnswer:

var mockThing = new MockThing();
when(mock.isDone).thenAnswer((_) => new Future.value(true));

I don't know if this a documentation, API, or just UX issue, or there is even a real issue - maybe mockito alone is mysterious so nobody assumes code to work great 100% of the time. We could make the API more verbose, i.e.:

thenAnswerSync<T>(T value);
thenAnswerAsync<T>(T Function() run);

But I don't know if that would help unless we threw on an invalid type at runtime.

Mock refers to "super", preventing it from being used as a mixin.

By supporting _givenHashCode, Mock refers to super, preventing its use a Mixin.

This means if I want to mock out unimplemented functions in an abstract class, I can't.

Here is an example of some interfaces and abstract implementations:

abstract class Foo {
  String bar();
}

abstract class AbstractFoo implements Foo {
  String bar() => baz();

  String baz();
}

I'd like to just extend AbstractFoo but also use Mock to mock out baz:

abstract class MockMixin {
  // Instead of 'noSuchMethod', so we don't use 'super.noSuchMethod'.
  handleNoSuchMethod(Invocation invocation) { ... }
}

// Test the implementation of 'AbstractFoo', and use stubs for the remaining abstract methods.
class MockFoo extends AbstractFoo with MockMixin {
  noSuchMethod(Invocation invocation) => handleNoSuchMethod(invocation);
}

void main() {
  var foo = new MockFoo();
  when(foo.baz()).thenReturn('baz');
  expect(foo.bar(), 'baz');
}

I think it would be alright if there was a base MockMixin. The current Mock could just extend that for people who would prefer extending it. I'd be OK with writing a PR for this feature, but wanted to suggest it first.

Allow `any` to work with Strong mode

This is a sibling issue to dart-lang/sdk#26036.

The issue is that we cannot use any with Strong mode turned on. For example:

int f(List<int> l) => l[0];

void main() {
  f(any);
}

Yields an analyzer error (dartanalyzer --strong a.dart): "Unsound implicit cast from dynamic to List".

I think we can solve this on the Mockito side, similar to Java Mockito's any().

I have a prototype implementation that uses the Strong mode type parameter comments:

/*=T*/ any/*<T>*/([/*=T*/ e = null]) => null;

The tricky part is that any would now return null, instead of the _ArgMatcher (again similar to Java Mockito's, and we would have to implement something like Java Mockito's reportMatcher(), maybe changing how the whole matching situation works...

What do you think? Any thoughts or other ideas?

Can't catch errors in when mocking Future.error

when returning a Future in a mock, tests will fail if there is any exception handling using async/await.

when(foo.doStuff()).thenReturn(new Future.error('mock error'));

In this case, any unit test using async/await and calling foo.doStuff will fail with "mock error". If async/await is not used, the mock error will be caught and the test will pass.

Heres an example project to help illustrate the problem. It is using the latest version of test and mockito.

@fibulwinter @kevmoo

Ability to mock classes using a 'mock()' function instead of having to define a Mock class

One of the things that's convenient about the Java Mockito library is that there is no need to explicitly define a Mock class. Currently when writing a Dart unit test the developer has to define these mock classes. This usually happens in the test file itself and sometime even duplicated across test files. This increases the friction when writing unit tests.

It would be convenient to just create a mock instance with something like

Cat mockCat = mock(Cat)

where mock() is a top-level function of mockito. This makes it similar to the Java library.

The implementation would be a Dart source transformer that parses mock(Type) and generates the Mock class and replaces the mock() call with new MockCat() (assuming MockCat is the name of the generated class - might be different in the actual implementation). mock(Type) might itself just be a mockito library function of return type dynamic that just returns null to keep the IDE happy.

Of course there will have to be considerations around warnings/errors to tell the user if they try to pass in anything other than a type that's known at compile time.

Has this been considered before? Please let me know and any comments as I would be interested in implementing this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.