말랑한 하루
[Flutter] TDD (Test Driven Development) - UseCase 본문
Clean Architecture에서 UseCase는 Repository를 활용하여 실질적인 비즈니스 로직을 구현하는 것에 초점을 맞추고 있습니다. UseCase Test는 결과를 잘 가져오는지 그리고 MockRepository를 활용한 결과 값과 UseCase의 결과 값이 같은지 비교합니다.
🍒 객체 선언 및 초기화
class MockTodoRepository extends Mock implements TodoRepository {}
void main() {
late TodoUseCase todoUseCase;
late MockTodoRepository mockTodoRepository;
setUp(() {
mockTodoRepository = MockTodoRepository();
usecase = TodoUseCase(mockTodoRepository);
});
...
}
🍒 더미 데이터 생성
UseCase의 결과 값에 대한 더미 데이터를 생성합니다.
final List<Todo> testTodos = [
Todo(id: 1, title: 'Todo 1'),
Todo(id: 2, title: 'Todo 2'),
];
🍒 테스트 선언/준비/실행/검증
🍇 테스트 선언
테스트 이름을 설정합니다. 해당 테스트가 어떤 동작을 검증하는지 쉽게 이해할 수 있도록 작성해야 합니다.
test('should get a list of Todo entities from the repository', () async {});
🍇 테스트 준비/실행/검증
테스트는 arrange/act/assert 즉, 준비/실행/검증 단계로 구조화되어 작성됩니다. 코드의 가독성을 높이고 어떤 부분에서 테스트가 실패했는지 명확하게 파악할 수 있습니다.
특히 여러 테스트 케이스를 작성할 때 일관성을 유지하고 테스트의 목적을 명확히 전달하는 것에 도움을 줄 수 있습니다.
test('should get a list of Todo entities from the repository', () async {
// arrange
when(mockTodoRepository.getTodoList()).thenAnswer((_) async => testTodos);
// act
final result = await todoUseCase(NoParams());
// assert
expect(result, equals(testTodos));
verify(mockTodoRepository.getTodoList());
});
초반에 설계 했던 테스트 목적에 대한 각 arrange/act/assert는 다음과 같은 모습으로 설계할 수 있습니다.
🍌 arrange
Repository Mock 객체를 활용하여 결과 값을 수신합니다. 결과 값은 “thenAnswer" 메소드를 활용해 생성해 논 더미데이터로 대체합니다.
🍏 thenAnswer
thenAnswer 메소드는 mockito 라이브러리에서 제공하는 기능입니다.
🍌 act
todoUseCase를 활용한 결과 값을 생성합니다.
🍌 assert
mock 객체를 활용하였으므로 mockito 라이브러리의 "verify" 메소드를 활용해 mock 객체가 정확히 동작하는지 확인합니다. 또한, 두 결과 값이 일치하는지 비교하기 위해 flutter_test 라이브러리의 "expact" 메소드를 활용합니다.
🍇 테스트 그룹
여러개의 테스트를 그룹화 할 수 있습니다. 관련된 테스트 케이스를 묶어서 Test Suite를 형성하고, 코드의 특정 부분이나 기능에 대한 다양한 측면을 검증하기 용이하게 만들어줍니다.
보통 가독성 향상/유사한 행위에 대한 통합 검증/효율적인 테스트 수행/코드 수정 용이성에 대한 이점을 얻을 수 있습니다.
"group" 메소드를 활용하고 전반적인 테스트를 통합하여 표현할 수 있는 문구 또는 함수명을 작성하는 것이 보편적입니다.
전체 소스코드는 다음과 같습니다.
class MockTodoRepository extends Mock implements TodoRepository {}
void main() {
late TodoUseCase todoUseCase;
late MockTodoRepository mockTodoRepository;
setUp(() {
mockTodoRepository = MockTodoRepository();
usecase = TodoUseCase (mockTodoRepository);
});
group('GetTodoList', () {
final List<Todo> testTodos = [
Todo(id: 1, title: 'Todo 1'),
Todo(id: 2, title: 'Todo 2'),
];
test('should get a list of Todo entities from the repository', () async {
// arrange
when(mockTodoRepository.getTodoList()).thenAnswer((_) async => testTodos);
// act
final result = await todoUseCase(NoParams());
// assert
expect(result, equals(testTodos));
verify(mockTodoRepository.getTodoList());
});
test('should throw an exception if the repository call fails', () async {
// arrange
when(mockTodoRepository.getTodoList()).thenThrow(Exception('Repository error'));
// act
final call = usecase;
// assert
expect(() => call(NoParams()), throwsException);
verify(mockTodoRepository.getTodoList());
});
});
}
🍒 테스트 진행
테스트는 루트 디렉토리에서 다음 명령어를 활용하여 실행할 수 있습니다.
flutter test {filePath}/{fileName}.dart
각 테스트 케이스에 대한 결과와 통과 여부에 대한 정보가 터미널에 출력됩니다.
00:10 +3: All tests passed!
00:10 +3 -1: Some tests failed.
테스트 결과는 시간/개수/내용으로 구분되어 표기되며 성공한 테스트는 "+", 실패한 테스트는 "-"로 표기됩니다.
테스트 코드에서 print 함수를 활용하여 명시적으로 작성한 내용과 함께 실패의 원인이 되는 에러 메세지가 터미널에 표기되므로, 참고하여 테스트 준비/실행/검증 단계를 반복해가면 됩니다.
'개발 > Flutter' 카테고리의 다른 글
[Flutter] Infinity Scroll (무한 스크롤) (0) | 2024.02.20 |
---|---|
[Flutter] TDD (Test Driven Development) - Riverpod (0) | 2024.02.08 |
[Flutter] TDD (Test Driven Development) - Repository (0) | 2024.02.06 |
[Flutter] TDD (Test Driven Development) - DataSource (0) | 2024.02.03 |
[Flutter] TDD (Test Driven Development) (0) | 2024.02.02 |