Flutter, Dart. Create anonymous class - class

Maybe it's really dumb question. But I cannot believe there is no resources, where it's described. Even from the official documentation. What I'm trying to do, it's create Anonymous class for the next function.
How to create Anonymous class in Dart with custom function something like next in Kotlin?
Handler(Looper.getMainLooper()).post(Runnable() {
#override
open fun run() {
//...
}
private fun local() {
//....
}
})

Dart does not support creating an anonymous class.
What you're trying to do is not possible.
On the other hand, you can create anonymous functions. So you could use that to mimic an anonymous class.
The idea is to add a constructor of your abstract class, that defer its implementation to callbacks.
abstract class Event {
void run();
}
class _AnonymousEvent implements Event {
_AnonymousEvent({void run()}): _run = run;
final void Function() _run;
#override
void run() => _run();
}
Event createAnonymousEvent() {
return _AnonymousEvent(
run: () => print('run'),
);
}
It's not strictly the same as an anonymous class and is closer to the decorator pattern. But it should cover most use-cases.

This is an alternative way, but not fully equivalent:
Problem, e.g.:
I would like to implement OnChildClickListener inline in my code without class. For this method:
void setOnChildClickListener(OnChildClickListener listener) {
...
}
Instead of this:
abstract class OnChildClickListener {
bool onChildClick(int groupPosition, int childPosition);
}
use this:
typedef OnChildClickListener = Function(int groupPosition, int childPosition);
And in code you can implement it in this way:
listView.setOnChildClickListener((int groupPosition, int childPosition) {
// your code here
});
In other words do not use abstract class, but use typedef.

Related

How to verify a method inside a method is called in mockito

I was doing some unit testing in flutter with mockito, and I feels unable to verify a method is called within another method. The code I've written so far as follows,
The class I want to test
class A {
void doSomething() {
callMe();
}
void callMe() {}
}
Mocked class
class MockA extends Mock implements A {}
The test I wrote,
test("Test method is called", () {
A a = new MockA();
a.doSomething();
verify(a.callMe()).called(1);
});
When I run the above test I am getting an error
No matching calls. All calls: MockA.doSomething()
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)
If i verify doSomething is called it works, but for a call on callMe within doSomething doesn't work. Is this the default behavior or am I doing something wrong? Please note I need to verify the callMe() method is called when doSomething() is called.
You mocked A and replaced it with MockA. Mocks have no implementation. MockA.doSomething() does nothing and does not and cannot call MockA.callMe().
That A.doSomething() calls A.callMe() should be considered an implementation detail of of doSomething(); making a test rely on that would tightly couple the test to the specific implementation and would be brittle.
You can't use a mock to verify the implementation of the thing being mocked. If you want to verify the implementation of A.doSomething(), you instead should use an actual object and verify observable properties on that object.
But if you still really want to do this, then you would need to modify A to not call methods on itself and to instead call methods on a provided object (i.e., "dependency injection"). For example:
class A {
final late A a;
A({A? a}) {
this.a = a ?? this;
}
void doSomething() {
a.callMe();
}
void callMe() {}
}
test("Test method is called", () {
var mockA = MockA();
var actualA = A(a: mockA);
actualA.doSomething();
verify(mockA.callMe()).called(1);
});
It's a bit unusual for a class to depend on a mock of itself, however, and it would not scale if you then want to verify calls made by callMe().
Another approach that would scale better (but with significantly more work) would be to create your own fake class that tracks method calls:
class TrackedA implements A {
int doSomethingCallCount = 0;
int callMeCallCount = 0;
#override
void doSomething() {
doSomethingCallCount += 1;
super.doSomething();
}
#override
void callMe() {
callMeCallCount += 1;
super.callMe();
}
}
But again, that's very brittle, and I would not recommend it.

Override/mock library functions for dart/flutter testing

I was wondering if there is a way to override library functions so they don't fire or just return something else.
import 'package:foo_package/exposing_foo_function.dart';
class TestableClass {
bool bar() {
return foo(); //foo is from the imported library
}
}
Test:
void main() {
test('TestableClass.bar() when foo_package.foo() returns false', () {
TestableClass testableClass = TestableClass();
// Something to make foo_package.foo() return false.
expect(testableClass.bar(), isFalse);
});
}
Things like mockito work by creating mock classes that implement the interface of the mocked class. That doesn't work for global and static functions, however.
What you instead can do is to avoid calling those global/static functions directly and instead call them through an extra level of indirection. For example:
import 'package:foo_package/exposing_foo_function.dart' as foo_package;
class TestableClass {
final bool Function() foo;
TestableClass({this.foo = foo_package.foo});
bool bar() {
return foo();
}
}
and then to test:
void main() {
test('TestableClass.bar() when foo_package.foo() returns false', () {
bool fakeFoo() => false;
TestableClass testableClass = TestableClass(foo: fakeFoo);
expect(testableClass.bar(), isFalse);
});
}
A similar approach is to wrap the global/static functions as instance methods of a class:
import 'package:foo_package/exposing_foo_function.dart' as foo_package;
class FooManager {
bool foo() => foo_package.foo();
}
var fooManager = FooManager();
class TestableClass {
bool bar() {
return fooManager.foo();
}
}
and then your tests can mock FooManager like any other class and set fooManager to the mocked version. (Or if you prefer dependency inversion to global variables, passing your mocked version of FooManager to TestableClass as a construction argument.)
Of course, all of the above will help only for your own calls that go through your wrappers. It won't help if code you don't control calls those functions. In that case, your best course of action might be to complain to the function's author about lack of testability.

What is the best way to mock 3rd party library's static method with Mockito in flutter

The approach I am following now is creating a wrapper around the class providing the static method, and then mocking this wrapper instead of mocking the real class, as in:
class TestClass {
final ThirdPartyClassWrapper _thirdPartyClassWrapper;
TestClass(this._thirdPartyClassWrapper);
void someMethod() {
_thirdPartyClassWrapper.doSomething();
}
}
class ThirdPartyClass {
static void doSomething() {}
}
class ThirdPartyClassWrapper {
void doSomething() {
ThirdPartyClass.doSomething();
}
}
//now I can mock the class and control the behaviour of the method
//but there is alot of boilerplate code
class MockThirdPartyClassWrapper extends Mock implements ThirdPartyClassWrapper{}
But as you see a lot of boilerplate is introduced.
So is there a better way to solve the problem?

how to call member methods inside a wrapper class without repeating the method definition inside the wrapper class?

let's assume i have a wrapper class that embeds a single memeber:
class wrapper {
public:
Object obj;
// the rest ...
};
if the member variable obj has some methods, how can i call the member variable method without explicitly defining methods in the wrapper class like this?
class wrapper{
public:
void foo { obj.foo (); }
int bar (int x) {return obj.bar(x); }
};
i know this is doable in python, but how can i have the same functionality in c++?
ps- please note i don't want to inherit from the member class. this wouldn't't be a wrapper class by definition. i want to achieve this through composition instead.
There are a few ways to handle this. One would be to create a getter to return the wrapper object and another is to override the typecast operator:
class Object {
public:
void foo() {cout << "test" << endl;}
};
class wrapper {
protected:
Object obj;
public:
operator Object&() {return obj;}
Object& getObject() {return obj;}
};
void f(A& a) {
a.foo();
}
int main() {
wrapper w;
((Object)w).foo();
w.getObject().foo();
f(w);
return 0;
}
As you can see, the typecast operator requires you to cast the wrapper object, except when passing as a parameter to the function f().
Also, in your example you already have the obj member as public so it is exposed. You could just:
wrapper w;
w.obj.foo();
Here's a discussion on that: What good are public variables then?

How to call java method from javascript method that located within another jsni method

public class A{
private void javaMethod(int a,int b){}
private native void init()/*-{
function OnMouseMove(e) {
//blow calling doesn't work
this.#p::javaMethod(Ljava/...teger;Ljava.../Integer;)(intVal,intVal);
}
}-*/;
}
As described above,how to make that invoking work?
Answered on the Google Group: https://groups.google.com/d/msg/google-web-toolkit/qE2-L4u_t4s/YqjOu-bUfsAJ
Copied here for reference and convenience:
First, int is not java.lang.Integer, so your method signature in JSNI is wrong; it should read javaMethod(II).
(I suppose the #p:: while javaMethod is defined in class A is over-simplification in your question, but is OK in your code)
You'll also probably have a problem with this, that might not be what you think it is. A common pattern is to assign the current object (this, at the time) to a variable that you'll reference from your closure:
var that = this;
…
function OnMouseMove(e) {
that.#p.A::javaMethod(II)(intVal, intVal);
}
You're doing two things wrong:
You're not defining the class name after #p, (assuming #p is actually just a shortened version of the real package's name);
You're attempting to pass java.lang.Integer in place of int. You should be saying (II) as the types, as described here.
Your code should look more like this:
package com.my.package;
public class ClassA {
private static void javaMethod(int a, int b) { ... }
public static native void init() /*-{
$wnd.javaMethod = function(a, b) {
return #com.my.package.ClassA::javaMethod(II)(a,b);
}
function OnMouseMove(e) {
$wnd.javaMethod(a,b);
}
}-*/;
}