guricode

[클린아키텍쳐]Clean Architecture -2 본문

앱/Flutter&Dart

[클린아키텍쳐]Clean Architecture -2

agentrakugaki 2025. 8. 30. 17:57

앞서 Dto를 작성했으니 인터페이스를 구현한다

 

인터페이스는 메서드 정의만하고 메서드 로직은 impl에서 구현한다. 레포지토리에서 이걸 참조해서 실제 구현된 내용이 수정되어도 인터페이스는 영향이 없도록 한다.

 

//movie_data_source.dart

import 'package:flutter_clean_arch/data/dto/movie_dto.dart';

///인터페이스는 수정이 안됌
abstract interface class MovieDataSource {
  Future<List<MovieDto>> fetchMovies();
}

추상클래스로 만들어 메서드 선언만 한다.

 

이제 인터페이스를 작성한다.

 

//movie_asset_data_source_impl.dart

import 'dart:convert';

import 'package:flutter/services.dart';
import 'package:flutter_clean_arch/data/data_source/movie_data_source.dart';
import 'package:flutter_clean_arch/data/dto/movie_dto.dart';

//인터페이스구현
class MovieAssetDataSourceImpl implements MovieDataSource {
  //테스트 할 수 있게 mock데이터로 넣어줄수 있게 객체구현할수있도록 코딩
  MovieAssetDataSourceImpl(this._assetBundle);

  //AssetBundle . 앱 패키지 안에 있는 정적 리소스(예: JSON, 이미지, 텍스트 파일 등)를 비동기로 불러올 수 있게 해주는 API
  // 흔히 rootBundle 또는 DefaultAssetBundle 을 통해 사용한다.
  final AssetBundle _assetBundle;

  @override
  Future<List<MovieDto>> fetchMovies() async {
    //assets불러오기
    final jsonString = await _assetBundle.loadString('assets/movies.json');
    //json으로 변환
    final list = jsonDecode(jsonString);

    //List로 list변수로 지정되어 json으로 변환된 jsonString을 List형태로 케스팅 후 map으로 돌려서 데이터들을 MovieDto로 변환 후 List로 바꿈
    return List.from(list).map((e) => MovieDto.fromJson(e)).toList();
  }
}


// flutter pub add -d mocktail로 테스트 패키지 추가
//mock데이터를 만들수있게해줌.-d : dev_dependencies에 추가됌

 

 

이제 인터페이스를 테스트코드로 테스트 해보자

test폴더에 Movie_asset_data_source_impl.dart파일을 만들어 테스트코드를 작성한다

 

import 'package:flutter/widgets.dart';
import 'package:flutter_clean_arch/data/data_source/movie_asset_data_source_impl.dart';
import 'package:flutter_clean_arch/data/data_source/movie_data_source.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';

class MockAssetBundle extends Mock implements AssetBundle {}

void main() {
  MockAssetBundle? mockAssetBundle;
  //MovieAssetDataSourceImpl?
  MovieDataSource? dataSource; //나중에 MovieAssetDataSourceImpl 객체가 들어올 수 있다

  //각각의 테스트 함수가 실행되기전에 셋팅할 로직들
  setUp(() {
    mockAssetBundle = MockAssetBundle();
    dataSource = MovieAssetDataSourceImpl(mockAssetBundle!);
  });

  //testcode
  test('MovieAssetDataSourceImpl : fetchMovies return data test', () async {
    when(() {
      //어떤 상황이 발생했을떄
      return mockAssetBundle!.loadString(any()); //어떤값도 들어올수 있게 any선언
    }).thenAnswer(
      //이렇게 리턴해준다
      (_) async => """
[{
    "title": "The Avengers",
    "released": "04 May 2012",
    "runtime": "143 min",
    "director": "Joss Whedon",
    "actors": "Robert Downey Jr., Chris Evans, Mark Ruffalo, Chris Hemsworth",
    "poster": "https://ia.media-imdb.com/images/M/MV5BMTk2NTI1MTU4N15BMl5BanBnXkFtZTcwODg0OTY0Nw@@._V1_SX300.jpg"
  }]
""",
    );

    final results = await dataSource!.fetchMovies();
    expect(results.length, 1);
  });
}