Coder Social home page Coder Social logo

Mock functions? about mockito HOT 13 OPEN

xster avatar xster commented on July 20, 2024 4
Mock functions?

from mockito.

Comments (13)

manoellribeiro avatar manoellribeiro commented on July 20, 2024 4

If you want to just create a mocked function to use as onTap on widget test environment, with mockito you can do something like that:

abstract class MyFunction {
  void call();
}
class MyFunctionMock extends Mock implements MyFunction {}

Test:

void main() {
 final mock = MyFunctionMock();
 ...

  // This is inside the the testWidgets callback 
  await tester.pumpWidget(
          widgetToBeTested(
            item: registeredListItem,
            onTap: mock,
          ),
        );

  //Logic to tap the widgetToBeTested

  verify(mock()).called(1);

}

from mockito.

matanlurey avatar matanlurey commented on July 20, 2024 1

I think the main issue here is that it won't be possible to create a single "Mock" function that could represent (statically) any function. In this particular case, it might honestly be simpler to just create a stub implementation of your function:

test('...', () {
  void stubDoSomething(a, b, c) {
    // ...
  }
};

from mockito.

zoechi avatar zoechi commented on July 20, 2024

A concrete example what you're trying to accomplish?

from mockito.

lrhn avatar lrhn commented on July 20, 2024

I'm not really proficient with mocks, but you should be able to mock the call method. The problem is having the correct function type.
A Dart object can only have one function type at a time (the type of the call method of its interface), so you can't have an object that has "any" function type and passes any is SomeTypedef test. You can make your mock implement a class that has a particular call method, and that makes it a function of that type, but only that type.

from mockito.

xster avatar xster commented on July 20, 2024

Example:

typedef A SomethingIWantToMock(B b, C c);

void somethingIWantToTest(D d, E e, SomethingIWantToMock mock) {
  [the code to test...]
  A a = mock(something, something);
  [more code to test...]
}

test('check that somethingIWantToTest interacts correctly with SomethingIWantToMock', () {
  SomethingIWantToMock mock = [make a mock...];
  when(mock).thenAnswer((Invocation invocation) => [use b, use c]);
  somethingIWantToTest(mock);
  assert
  assert
  verify(mock)
  verify(mock)
});

More or less the same as class mocking but with functions.

from mockito.

xster avatar xster commented on July 20, 2024

cc @cbracken FYI

from mockito.

srawlins avatar srawlins commented on July 20, 2024

Hi @xster yeah this is, with the current implementation, impossible ☚ī¸ . When you wrap a method call with when(...), mockito does literally call the method, but it routes directly to the noSuchMethod method of Mock. We have no way of routing a call of a top-level method.

I think @matanlurey 's suggestion should work perfectly if you get to inject the function into somethingIWantToTest.

from mockito.

noamraph avatar noamraph commented on July 20, 2024

It's now very easy to mock functions. You just need to mock an abstract class that contains all the functions you need as methods, and then pass the methods as the needed functions.

Here's a full example:

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

import 'example_test.mocks.dart';

/// The function to test
Future<DateTime> getCurrentTime(
    Future<String> Function(String) postRequest) async {
  String r = await postRequest('getCurrentTime');
  return DateTime.fromMillisecondsSinceEpoch(int.parse(r) * 1000, isUtc: true);
}

abstract class MyFuncs {
  Future<String> postRequest(String name);
}

@GenerateMocks([MyFuncs])
void main() {
  test('getCurrentTime', () async {
    final myFuncs = MockMyFuncs();
    when(myFuncs.postRequest('getCurrentTime'))
        .thenAnswer((_) async => '1647249645');
    final dt = await getCurrentTime(myFuncs.postRequest);
    expect(dt, DateTime.utc(2022, 3, 14, 9, 20, 45));
  });
}

from mockito.

natebosch avatar natebosch commented on July 20, 2024

@srawlins - I just saw the pattern of mocking an abstract class for it's tearoffs used in a code review and it surprised me at first.

Do you think it would be reasonable to more directly support mocking callbacks now that we have codegen? We could feasibly turn Future<String> Function(String) into a full mock class with a method that could be torn off, without asking the user to write the abstract class around it too.

A few points to consider:

  • How would we name them? Maybe we'd need to configure them in a map keyed by a name? {'postRequest': Future<String> Function(String)}
  • How would we surface them? We don't necessarily need to expose the fact that they are tearoffs of a regular Mock
Future<String> Function(String) mockPostRequest() => _MockPostRequest().call;

from mockito.

srawlins avatar srawlins commented on July 20, 2024

This is a very cool idea. Something like MockSpec<Future<String> Function(String)>(as: #mockPostRequest).

from mockito.

neokree avatar neokree commented on July 20, 2024

About this point, I have a slightly different problem that I don't know how to solve myself:

// application/repository/todo.dart
import 'package:flutter/foundation.dart';
import 'package:port_domain/networking.dart';
import 'package:todo/domain/todo.dart';

class TodoRepository {
  final RestClient _client;
  final String _baseUrl;

  List<Todo> todos = [];

  TodoRepository(this._client, this._baseUrl);

  Future<void> fetchFromRemote() async {
    Response groupRes = await _client.get(
      _baseUrl + 'api/todos',
      parser: (data) => compute(Todo.fromJsonList, data as List),
    );
    if (groupRes is Success) {
      todos.clear();
      todos.addAll(groupRes.result);
    }
  }
}
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:port_domain/networking.dart';
import 'package:todo/application/repository/todo.dart';

@GenerateMocks([RestClient])
import 'repository_todo_test.mocks.dart';

void main() {
  late RestClient client;
  late TodoRepository repository;

  setUp(() {
    client = MockRestClient();
    repository = TodoRepository(client, '');
  });

  group('TodoRepository', () {
    test('should have entities available after a successful fetch', () async {
      var todoList = [const Todo(id: 1)];
      when(
        client.get(
          'api/todos',
          parser: any, // <-- This fails because any isn't supported
        ),
      ).thenAnswer((_) async => Success<List<Todo>>(todoList));
      await repository.fetchFromRemote();

      expect(repository.todos, equals(todoList));
    });
  });
}

Can someone point me out to a way to test it? The problem here is that the Repository creates a closure that should be identified by mockito as the same function.

from mockito.

yanok avatar yanok commented on July 20, 2024

@neokree You have to use anyNamed('parser') here. That's a limitation of Mockito implementation.

from mockito.

yanok avatar yanok commented on July 20, 2024

Regarding adding support for mocking functions: definitely doable with codegen, but not sure it's a high priority for us. Will be happy to review changes.

from mockito.

Related Issues (20)

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.