Flutter TDD Clean Architecture Course [11] - Bloc Implementation 1/2

แชร์
ฝัง
  • เผยแพร่เมื่อ 16 ก.ย. 2024

ความคิดเห็น • 72

  • @flarecodeflit4823
    @flarecodeflit4823 5 ปีที่แล้ว +44

    Bro you should make one more playlist, in which make a multi-page app using TDD and bloc. It will help us a lot. Always love your work #resocoder

    • @andresmaniotto1486
      @andresmaniotto1486 4 ปีที่แล้ว +2

      totally, I started a few time and I kind of lost on how to do some simples things with bloc, normally, things that suppost to happen in a multi-page app (real life, right?). I am coming from Xamarin, and in MVVM every thing seens so simple and connected rsrsrs

  • @notrustyspoon
    @notrustyspoon ปีที่แล้ว +5

    Since the previous way shown in the video no longer works for later Bloc versions, this is what worked for me on Flutter Bloc 8.1.1
    test('should emit [Error] when input is invalid', () async* {
    when(mockInputConverter.stringToUnsignedInteger(any))
    .thenReturn(Left(InvalidInputFailure()));
    final expected = [
    Empty(),
    const Error(message: INVALID_INPUT_FAILURE_MESSAGE)
    ];
    expectLater(bloc.stream.asBroadcastStream(), emitsInOrder(expected));
    bloc.add(const GetTriviaForConcreteNumber(tNumberString));
    });
    My NumberTriviaBloc class looks like this;
    class NumberTriviaBloc extends Bloc {
    final GetConcreteNumberTrivia getConcreteNumberTrivia;
    final GetRandomNumberTrivia getRandomNumberTrivia;
    final InputConverter inputConverter;
    NumberTriviaBloc({
    required GetConcreteNumberTrivia concrete,
    required GetRandomNumberTrivia random,
    required this.inputConverter
    }) : getConcreteNumberTrivia = concrete,
    getRandomNumberTrivia = random,
    super(Empty()) {
    on (numberTriviaEventObserver);
    }
    FutureOr numberTriviaEventObserver(event, emit) async* {
    if (event is GetTriviaForConcreteNumber) {
    final inputEither = inputConverter.stringToUnsignedInteger(event.numberString);
    yield* inputEither.fold(
    (failure) async* {
    yield const Error(message: INVALID_INPUT_FAILURE_MESSAGE);
    },
    (integer) => throw UnimplementedError());
    }
    }
    }

  • @nadous74
    @nadous74 4 ปีที่แล้ว +46

    bloc.dispatch should be bloc.add with flutter_bloc ^2.0

    • @JonesDTaylor
      @JonesDTaylor 4 ปีที่แล้ว

      send a pr :)

    • @gogalcloud
      @gogalcloud 3 ปีที่แล้ว +6

      if your test still fails then change to the following :
      test('should emit [Error] when the input is invalid', () async {
      // arrange
      when(mockInputConverter.stringtoUnsignedInt(any))
      .thenReturn(Left(InvalidInputFailure()));
      // assert later
      final expected = [
      //Empty(),
      Error(message: INVALID_INPUT_FAILURE_MESSAGE),
      ];
      expectLater(bloc.stream, emitsInOrder(expected));
      // act
      bloc.add(GetTriviaForConcreteNumber(tNumberString));
      });

    • @andresnaranjo48
      @andresnaranjo48 3 ปีที่แล้ว +1

      @@gogalcloud Thanks a lot!

  • @yipyip255
    @yipyip255 4 ปีที่แล้ว +31

    if your following this tutorial later after the bloc update. bloc.state does not return a list of states, but the latest state. To add a stream type.
    expectLater(
    bloc.asBroadcastStream(),
    emitsInOrder(expected),
    );

    • @imagineabout4153
      @imagineabout4153 4 ปีที่แล้ว +1

      Saved me a lot of time. Thank you.

    • @raffos92
      @raffos92 3 ปีที่แล้ว +1

      doesn't work for me :( both tests doesn't work... should call inputConverter and should emit error

    • @raffos92
      @raffos92 3 ปีที่แล้ว

      I have solved in that way:
      expectLater(
      bloc.asBroadcastStream(),
      emits(Error(message: INVALID_INPUT_FAILURE_MESSAGE)),
      );
      i don't know why he doesn't emit the first state

    • @gogalcloud
      @gogalcloud 3 ปีที่แล้ว +2

      Resocoder should have atleast updated the bloc code for the latest version into their repositories at gethub @@raffos92

    • @thcdenton
      @thcdenton 2 ปีที่แล้ว

      thanks homie

  • @sandromaglione
    @sandromaglione 4 ปีที่แล้ว +26

    I got an error while testing the Error. I believe it was because of Bloc 1.0.0 new release. Basically bloc.state returns the current state and the test failed reporting
    'ERROR: Expected: should do the following in order:
    * emit an event that Empty:
    * emit an event that Error:
    Actual: Empty:
    Which: was not a Stream or a StreamQueue'
    I solved it by changing bloc.state to bloc.cast()

    • @etiennetheodore
      @etiennetheodore 4 ปีที่แล้ว +1

      Thanks works for me. :)

    • @mane86
      @mane86 4 ปีที่แล้ว

      Works for me too! Thanks! Do you know the difference between cast() and state? Could you help me Reso Coder?

    • @enriqueortiz7251
      @enriqueortiz7251 4 ปีที่แล้ว +8

      With the new flutter_bloc release you just need to use bloc not bloc.state or bloc.cast() ResoCoder just made a good primer video for the bloc_test package that touches on these points and as always is great!

    • @JonesDTaylor
      @JonesDTaylor 4 ปีที่แล้ว +1

      Update your code following this video: th-cam.com/video/S6jFBiiP0Mc/w-d-xo.html

  • @juantaverasiv741
    @juantaverasiv741 5 ปีที่แล้ว +5

    I was eagerly waiting for this video.
    Currently implanting all these techniques in my Flutter project.
    Thanks for the awesome work!

  • @abderrahmansettani9843
    @abderrahmansettani9843 5 ปีที่แล้ว +4

    Thanks a lot friend this is reaally the most pro tutoriels out there .

  • @SEOTADEO
    @SEOTADEO 2 ปีที่แล้ว +1

    3:10 "optional but also required"... reminds me of that "Well yes but actually no" meme hahaha

  • @jesselima_dev
    @jesselima_dev 4 ปีที่แล้ว +2

    For a better readability I renamed classes ans objects instance:
    GetRandomNumberTrivia to GetRandomNumberTriviaUseCase
    and randomNumberTriviaUseCase
    GetConcreteNumberTrivia to GetConcreteNumberTriviaUseCase
    and concreteNumberTriviaUseCase

  • @EdissonReinozo
    @EdissonReinozo 4 ปีที่แล้ว +1

    Great! You are really good at explaining!
    I finally understand async* and yield*.

  • @jeremydormevil5220
    @jeremydormevil5220 2 ปีที่แล้ว +4

    blocTest(
    'emit [NumberTriviaError] when the input is invalid',
    build: () {
    when(mockInputConverter.stringToUnsignedInteger(any))
    .thenReturn(Left(InvalidInputFailure()));
    return numberTriviaBloc;
    },
    act: (bloc) => bloc.add(const GetTriviaForConcreteNumber(tNumberString)),
    expect: () => [isA()],
    );

  • @darshitchokshi8877
    @darshitchokshi8877 3 ปีที่แล้ว

    All the videos related to Clean architecture are awesome. You have very well explained the stuffs. Love your channel. #resocoder

  • @christianonwe2045
    @christianonwe2045 5 ปีที่แล้ว +2

    I really love you for your work. Thanks

    • @ResoCoder
      @ResoCoder  5 ปีที่แล้ว +2

      Thanks for watching!

  • @thomasmabika7291
    @thomasmabika7291 5 ปีที่แล้ว +1

    I don't know if it's just me, but I feel like this approach is really excellent for a one man team. If you have to add members to that team, you'd really have to sit them down and teach them about this approach thereby losing production time, I don't know...great series though.

    • @tannermeade
      @tannermeade 5 ปีที่แล้ว +2

      That's a reality that exists in most development contexts. Now there is this video series that you can tell them to go through, so everyone can be on the same page.

  • @marialijideveloper2006
    @marialijideveloper2006 4 ปีที่แล้ว +2

    Hi 'Sensei' thanks for wonderful work !! , by the way , when you add bloc.dispatch , currently it isn't on bloc, because In v1.0.0 of the bloc library, all blocs are now Sinks. This means we can start using the traditional add sink api in order notify the bloc of a new event instead of dispatch.

  • @TheBillionDollarSaaS
    @TheBillionDollarSaaS 5 ปีที่แล้ว +1

    Thanks my friend. Keep it up!

  • @rhutikgiradkar
    @rhutikgiradkar 3 ปีที่แล้ว +1

    For the last test use bloctest instead
    blocTest(
    'should emit [Error] when the input is invalid',
    build: () {
    when(mockInputConverter.stringToUnsignedInteger(any))
    .thenReturn(Left(InvalidInputFailure()));
    return bloc;
    },
    act: (bloc) => bloc.add(GetTriviaForConcreteNumber(tNumberString)),
    expect: () => [Error(message: INVALID_INPUT_FAILURE_MESSAGE)],
    );
    });
    and
    yield* inputEither.fold(
    (failure) async* {
    yield Error(message: INVALID_INPUT_FAILURE_MESSAGE);
    },
    (number) async* {
    print(number);
    },
    );

    • @gogalcloud
      @gogalcloud 3 ปีที่แล้ว +1

      or you can do some changes like this :
      test('should emit [Error] when the input is invalid', () async {
      // arrange
      when(mockInputConverter.stringtoUnsignedInt(any))
      .thenReturn(Left(InvalidInputFailure()));
      // assert later
      final expected = [
      //Empty(),
      Error(message: INVALID_INPUT_FAILURE_MESSAGE),
      ];
      expectLater(bloc.stream, emitsInOrder(expected));
      // act
      bloc.add(GetTriviaForConcreteNumber(tNumberString));
      });
      Important: First of you are still facing error is because you have to implement right Side of the fold also:
      if (event is GetTriviaForConcreteNumber) {
      final inputorerror =
      inputConverter.stringtoUnsignedInt(event.numberString);
      yield* inputorerror.fold((l) async* {
      yield Error(message: INVALID_INPUT_FAILURE);
      }, (r) async* {
      concreteNumberTrivia(Params(number: r));
      });
      }

  • @serpentarius5074
    @serpentarius5074 4 ปีที่แล้ว +3

    you should remake this tutorial with the current version of bloc. I saw your github project for this tutorial the bloc dependecy still at v5.0.0 compared to current bloc v6.0.1

  • @dawidniegrebecki2205
    @dawidniegrebecki2205 4 ปีที่แล้ว

    Great video!!!

  • @6957-c5k
    @6957-c5k 4 ปีที่แล้ว +1

    watch out for this line *expectLater(bloc, emitsInOrder(expected))*

  • @baptiste600
    @baptiste600 4 ปีที่แล้ว

    Hi thanks for this tutorial. I was wondering why did you pass usecases dependencies one by one for the bloc implementation and not directly the repository Interface ? Can't really understand the role of usescases.... Seems like another layer of abstraction but what for ? Thanks again !

  • @kevinhorasia3298
    @kevinhorasia3298 ปีที่แล้ว

    For the last test, since I try to find minimum changes needed in order for the test to work.
    just change async to async* in number_trivia_bloc_test.dart for that test.
    async => gives you a Future
    async* => gives you a Stream

    • @kevinhorasia3298
      @kevinhorasia3298 ปีที่แล้ว

      DO NOT USE async*!!! using async* will not show error when the expected is wrong.
      Instead in expectLater change [bloc.state] to [bloc.stream]

  • @ryanb55
    @ryanb55 4 ปีที่แล้ว

    Excellent video tutorial and my only feedback might be that the flutter_bloc library has changed so rapidly that a few parts just didn't work. such as bloc.dispatch is no longer a bloc method. Since the making of this video, less than 2 months ago, flutter_bloc has gone from beta to v1.0.0 to now v2.0.0. Perhaps a single video update on this library alone might be enough.

    • @JonesDTaylor
      @JonesDTaylor 4 ปีที่แล้ว

      I think the best thing to do is to pull the repo and do the updates then send a PR.

    • @ResoCoder
      @ResoCoder  4 ปีที่แล้ว

      I have updated the repo a month ago.

  • @IbrahimMohamed-dz7ih
    @IbrahimMohamed-dz7ih 2 ปีที่แล้ว +3

    the new code for the updated version of bloc
    test('should emit [error] when the input is invalid', () {
    when(() => mockInputConverter.stringToUnsignedInt(any()))
    .thenReturn(Left(InvalidInputFailure()));
    final expected = [
    // Empty(),
    Error(message: INVALID_INPUT_FAILURE_MESSAGE),
    ];
    expectLater(bloc.stream.asBroadcastStream(), emitsInOrder(expected));
    bloc.add(GetTriviaForConcreteNumber(tNumberString));
    });

  • @tahamalas1322
    @tahamalas1322 5 ปีที่แล้ว

    I'd like to know if it is possible to make the state a built_value object and still get the equatable feature with it! Because I really loved the built_value of the state and the immutabality of it, Thank you so much

    • @tahamalas1322
      @tahamalas1322 5 ปีที่แล้ว

      Because when changing the state I'd like to preserve the old data of the state if not changed, so it possible to do that without built_value or not?

  • @serragnoli
    @serragnoli 4 ปีที่แล้ว

    Amazing tutorial.
    Where would you execute flutter auth plugins (like flutter_facebook_login) from?
    Thanks

  • @etiennetheodore
    @etiennetheodore 5 ปีที่แล้ว

    Thanks again keep going :) !

  • @dennisbarzanoff9025
    @dennisbarzanoff9025 4 ปีที่แล้ว

    Isn't the state a cold observable? It should wait for you to expect it, shouldn't it?

  • @yashpaneliya1362
    @yashpaneliya1362 3 ปีที่แล้ว

    I am getting this error in test.
    Unhandled error UnimplementedError occurred in Instance of 'NumberTriviaBloc'.

  • @travisbrannon401
    @travisbrannon401 3 ปีที่แล้ว +3

    Code in Repo does not work for this test.
    I am using null safe flutter_bloc version 7.0.1. This test code doesn't work as provided. The stream is not emitting the Empty state. It's only emitting the Error state. Plus, you need to wire the the expectLater call to bloc.stream.asBroadcastStream() To get the test to work using null safe flutter_bloc.
    The below code works for this test:
    group('NumberTriviaBloc 2', () {
    test('should emit [NumberTriviaErrorState] when the input is invalid', () async {
    // arrange
    when(mockInputConverter.stringToUnsignedInteger(any))
    .thenReturn(Left(InvalidInputFailure()));
    // assert later
    final expected = [
    // the initial state is always emitted first
    // EmptyNumberTriviaState(),
    ErrorNumberTriviaState(message: INVALID_INPUT_FAILURE_MESSAGE)
    ];
    expectLater(bloc.stream.asBroadcastStream(), emitsInOrder(expected));
    // act
    bloc.add(GetTriviaForConcreteNumberEvent(numberString: 'xyz'));
    });
    });

  • @pathakvivek7865
    @pathakvivek7865 5 ปีที่แล้ว +1

    when is this Number Trivia project going to finish..?

    • @ResoCoder
      @ResoCoder  5 ปีที่แล้ว +2

      In 2 weeks PLUS the full code is already on GitHub.

  • @loicngou9592
    @loicngou9592 4 ปีที่แล้ว

    Hello resocoder thanks for your greats tutorials, I used bloc+ flutter_bloc in my app, i noticed that I need at least one bloc per page, is it normal or I didn't well-understood bloc pattern with flutter_bloc? Is there a way to share more than one type of data per bloc? for example i ve implemented shop app with favorite item feature, i had to create 1 bloc for favorite item, 1 for home page item and one for item itself, could i encapsulate all this in a "shopBloc" ?

    • @honzabittner1856
      @honzabittner1856 4 ปีที่แล้ว +1

      You need one bloc per one big enough functionality. You can have 1 and you can have even more blocs you use in your app page. Some of the Blocs might be shared across the pages, because of blocs cover functionality, not pages.
      If you using general BLoC conventions, you might have one bloc for the whole shop app, but because you are, probably using, the package:bloc (from Felix Angelov) implementation, which only have 1 way in, 1 way out, you cannot, for example, create an effective solution for having the whole shop logic in one bloc. But this is a good thing because we want to split our functionality and states per functionality provide us better testability.
      You can find more information about how Bloc (package:bloc) works at bloclibrary.dev/#/

  • @imagineabout4153
    @imagineabout4153 4 ปีที่แล้ว

    You the outro song is so danceable

  • @ShadowInfest
    @ShadowInfest 5 ปีที่แล้ว

    Can't watch the tutorial today... One of my hdds crashed and I decided to reinstall my system from scratch. When manjaro and win 10 work again I will go for it 🤘🙈

    • @ResoCoder
      @ResoCoder  5 ปีที่แล้ว +1

      Oh my! How do you find Manjaro compared to Debian-based distros? I'm on PopOS (basically Ubuntu).

    • @ShadowInfest
      @ShadowInfest 5 ปีที่แล้ว

      @@ResoCoder I used Ubuntu at first like most Linux newbies. Though I'm still one. But package management is far better in arch distros in my opinion. It just runs smooth no bugs on installation e.g. on my Raspberry Pi 4. The only problem I had so far was getting blizzard games to run... Because of Nvidia Drivers... I guess Pop OS is there in a better shape 😅

  • @fducha7175
    @fducha7175 4 ปีที่แล้ว

    hi, I updated bloc to 1.0.0 version and get fail of the last test. Can you find out what is wrong, what was broke?

    • @honzabittner1856
      @honzabittner1856 4 ปีที่แล้ว +1

      I suppose it is because of the package:bloc since v1.0.0 implements Stream and Sink API, therefore you only need to use `myBloc` to get the stream of events, not `myBloc.state`. Take a look at the changelog github.com/felangel/bloc/blob/master/packages/bloc/CHANGELOG.md

  • @marcusxavierr6616
    @marcusxavierr6616 4 ปีที่แล้ว

    The tests don't pass in flutter 1.20. So downgrade to flutter 1.17.5