Unit Test Concrete Method of Abstract Class in Dart - flutter

I have an abstract class written in Dart, that not only contains abstract method but also contains concrete methods like below:
abstract class Person {
void speak();
Foot getFoot();
void walk() {
getFoot().move();
}
}
class Foot {
void move() {
}
}
Test:
class MockPerson extends Person {
#override
Foot getFoot() {
return Foot();
}
#override
void speak() {
}
}
void main() {
late MockPerson sut;
setUp(() {
sut = MockPerson();
});
test('test walk', () {
/// ??
});
}
I tried to created mock of Person to be able to test against it. But I'm not sure how can I write unit test for walk() method?

Related

Call super method of super class from child class

I have an abstract class A:
abstract class A {
Future<String> firstMethod();
}
and I implemented this abstract class:
class Aimp implements A {
#override
Future<String> firstMethod() async {
return "test";
}
}
I have created another abstract class:
abstract class B extends A {
Future<String> secondMethod();
}
and I implemented this abstract class:
class Bweb extends B {
#override
Future<Object> secondMethod() async {
final t = //I want to call firstMethod()
if(t.isNotEmpty()) // do sth
}
}
In the implementation of secondMethod(), how can I call the implementation of firstMethod()?
I don't want to use mixin.
I try to use with instead:
abstract class A {
Future<String> firstMethod();
}
class Aimp implements A {
#override
Future<String> firstMethod() async {
return "test";
}
}
abstract class B with Aimp {
Future<String> secondMethod();
}
class Bweb extends B {
#override
Future<String> secondMethod() async {
final String t = await firstMethod(); //Your firstMethod function
if(t.isNotEmpty) {
return t;
}
return '';
}
}
Then you need an object of Aimp class item as a field of Bweb class. Or place A class as a field for the B one.

How to convert bloc to cubit?

I use bloc but I want to remake this code into cubit because I don't have to use event, I can remove them. I tried to do this, but I got an error and the code did not work, but I don’t understand what I could be wrong about. I will be grateful if you help me correctly conveyed Tell me, how can I convert bloc into cubit correctly (I don’t have to use the event)?
bloc
class ConnectedBloc extends Bloc<ConnectedEvent, ConnectedState> {
StreamSubscription? subscription;
ConnectedBloc() : super(ConnectedInitial()) {
on<OnConnectedEvent>((event, emit) => emit(ConnectedSucess()));
on<OnNotConnectedEvent>((event, emit) => emit(ConnectedFailure()));
var resultCon = Connectivity().checkConnectivity();
if (resultCon == ConnectivityResult.wifi ||
resultCon == ConnectivityResult.mobile) {
add(OnConnectedEvent());
} else {
add(OnNotConnectedEvent());
}
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
if (result == ConnectivityResult.wifi ||
result == ConnectivityResult.mobile) {
add(OnConnectedEvent());
} else {
add(OnNotConnectedEvent());
}
});
#override
Future<void> close() {
subscription?.cancel();
return super.close();
}
}
}
event
abstract class ConnectedEvent {}
class OnConnectedEvent extends ConnectedEvent {}
class OnNotConnectedEvent extends ConnectedEvent {}
state
abstract class ConnectedState {}
class ConnectedInitial extends ConnectedState {}
class ConnectedSucess extends ConnectedState {}
class ConnectedFailure extends ConnectedState {}
home
home: BlocConsumer<ConnectedBloc, ConnectedState>(
listener: ((context, state) {
if (state is ConnectedFailure) {
Remove your event classes and extend ConnectivityCubit class from Cubit instead of Bloc.
abstract class ConnectedState {}
class ConnectedInitial extends ConnectedState {}
class ConnectedSuccess extends ConnectedState {}
class ConnectedFailure extends ConnectedState {}
class ConnectivityCubit extends Cubit<ConnectedState> {
late final StreamSubscription connectivityStreamSubscription;
final Connectivity connectivity = Connectivity();
ConnectivityCubit() : super(ConnectedInitial()) {
connectivityStreamSubscription =
connectivity.onConnectivityChanged.listen((result) {
if (result == ConnectivityResult.wifi ||
result == ConnectivityResult.mobile) {
emit(ConnectedSuccess());
} else {
emit(ConnectedFailure());
}
});
}
#override
Future<void> close() {
connectivityStreamSubscription.cancel();
return super.close();
}
}

Manage Global Events by bloc

I am trying to find solution to manage async queries. For example, i have internet shop and i want to update all products and categories when city is changed. And i don't want to keep all async logic on ui. In order to achieve this result, i've created this bloc:
class AppEvent {
String message;
AppEvent({this.message = ''});
}
class EventsBlock extends Bloc<AppEvent, AppEvent> {
EventsBlock() : super(AppEvent());
#override
Stream<AppEvent> mapEventToState(AppEvent event) async* {
yield event;
}
}
final events = EventsBlock();
Then, i can use it like this:
class CityCubit() {
CityCubit() : super(CityState());
Future<void> changeCity() async {
await api.changeCity();
events.add(AppEvent(message: 'cityChanged'));
}
}
class CategoryCubit extends Cubit<CategoryState> {
CategoryCubit() : super(CategoryEmptyState()) {
events.stream.listen((e) {
if(e.message == 'cityChanged') {
fetchCategories();
}
});
};
Future<void> fetchCategories() async {
//fetch categories
}
}
class ProductCubit extends Cubit<ProductState> {
ProductCubit() : super(ProductEmptyState()) {
events.stream.listen((e) {
if(e.message == 'cityChanged') {
fetchProducts();
}
});
};
Future<void> fetchProducts() async {
//fetch products
}
}
It's something like eventBus pattern. But i am not sure that it's a correct way to use bloc. I've tried to use redux + redux saga, but it has a lot of boilerplate and i believe that flutter has better solution to manage things like that.
Your general idea is ok, but I can't see a real need for the EventsBloc class. In fact, it is kinda strange that you use the same class for the events and for the states of this bloc, and simply yield the event you receive. It's like EventsBloc could be a simple stream.
Here's a way to go, turning CityCubit into an actual bloc (and also with some error handling, which is something you can do gracefully with bloc):
abstract class CityState {}
class CityInitial extends CityState {}
class CityLoadingCities extends CityState {}
class CityCitiesLoaded extends CityState {}
class CityLoadError extends CityState {}
abstract class CityEvent {}
class CityLoadCities extends CityEvent {}
class CityBloc<CityEvent, CityState> {
CityBloc() : super(CityInitial());
#override
Stream<AppEvent> mapEventToState(CityEvent event) async* {
if(event is CityLoadCities) {
yield CityLoadingCities();
try {
await api.changeCity();
yield CityCitiesLoaded();
} catch (error) {
yield CityLoadError();
}
}
}
void changeCity() {
add(CityLoadCities());
}
}
Now you can do this inside any other bloc:
instanceOfCityBloc.listen((cityState) {
if(cityState is CityCitiesLoaded){
// do stuff
}
});
I ended up with this code:
class CityChangedEvent {
int cityId;
CityChangedEvent(this.cityId);
}
EventBus eventBus = EventBus();
mixin EventBusMixin {
StreamSubscription<T> listenEvent<T>(void Function(T) subscription) =>
eventBus.on<T>().listen(subscription);
void shareEvent<S>(S event) => eventBus.fire(event);
}
class CityCubit extends CityCubit<CityState> with EventBusMixin {
CityCubit() : super(CityInitialState());
Future<void> changeCity(cityId) async {
try {
emit(ChangeCityLoadingState());
final result = await api.changeCity(cityId);
if(result.success) {
emit(ChangeCitySuccessState());
shareEvent(CityChangedEvent(cityId));
}
} catch (_) {
emit(ChangeCityErrorState());
}
}
}
class CategoryCubit extends Cubit<CategoryState> with EventBusMixin {
CategoryCubit() : super(CategoryEmptyState()) {
listenEvent<CityChangedEvent>((e) {
fetchCategories(e.cityId);
);
}
Future<void> fetchCategories(cityId) async {
try {
emit(CategoryLoadingState());
final categoriesList = await fetchCategoriesApi();
emit(CategoryLoadedState(categories: categoriesList));
} catch (_) {
emit(CategoryErrorState());
}
}
}
Now, i can communicate between blocs without the need to instantiate or inject their instances. Thanks to this library https://pub.dev/packages/event_bus

class constructor after inheritance

i'm new to flutter i can't get the constructor to work which is in comment,
but the other constructor works, why? thank you
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: ImageEditor()
// child: PhotoView(imageProvider: AssetImage("Assets/img/carte.png"),)
);
}
}
class ImageEditor extends PhotoView {
// ignore: missing_required_param
ImageEditor():super(imageProvider: AssetImage("Assets/img/carte.png"),){
init();
}
//ImageEditor(){
// super(imageProvider: AssetImage("Assets/img/carte.png"),);
// init()
// }
void init(){
if(imageProvider!=null) {
print("il y a peut etre moyen de dessiner sur l'image");}
}
}
This is what you call a super constructor.
ImageEditor():super(imageProvider: AssetImage("Assets/img/carte.png")){
init();
}
Normally, a subclass can inherit all the variables and function from the parent class(using the extends) keyword, but you cannot access its constructor.
Using the : super() argument, you can however call the constructor from the parent class. You can only do it that way, that is simply the syntax.
Example:
class Class1 {
Class1(String name) {
print("Hello $name");
}
}
class Class2 extends Class1 {
Class2() : super("Tom") { //the name from above
print("Hello World");
}
}
void main() {
Class2 test = new Class2();
}
The output would be(in that order):
Hello Tom
Hello World

How to define concrete type from generic in Dart?

I am trying to make multiple Controller Types foo multiple Models for use with Provider in Flutter.
This is my Code:
//generic controller
class ModelController<E extends HiveObject> extends ChangeNotifier {
Box<E> _db;
ModelController(Box<E> db) {
_db = db;
}
// getters
List<E> get all => _db.values;
// create
void add(E item) {
_db.add(item);
notifyListeners();
}
void update(E item) {
item.save();
notifyListeners();
}
// delete
void delete(E item) {
item.delete();
notifyListeners();
}
}
class PacketController extends ModelController<Packet>{
PacketController(Box<Packet> db) : super(db);
}
The code for class PacketController is the only way I found to create a concrete type from a generic one.
Question:Is there a better way for this?
Shortly, I am looking for something like typedef in c++:
typedef IntVector std::vector<int>