Skip to content

Commit

Permalink
feat: 天気情報取得のユニットテスト作成
Browse files Browse the repository at this point in the history
  • Loading branch information
yuk1ch1 committed May 16, 2024
1 parent 0a14a6a commit 57b4da8
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 0 deletions.
147 changes: 147 additions & 0 deletions test/weather_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_training/model/weather.dart';
import 'package:flutter_training/model/weather_condition.dart';
import 'package:flutter_training/model/weather_exception.dart';
import 'package:flutter_training/model/weather_request.dart';
import 'package:flutter_training/model/weather_response.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:yumemi_weather/yumemi_weather.dart';

import 'weather_test.mocks.dart';

@GenerateNiceMocks([MockSpec<YumemiWeather>()])
void main() {
late MockYumemiWeather mockYumemiWeather;
late ProviderContainer container;
final request = WeatherRequest(
area: 'tokyo',
date: DateTime.now(),
);

setUp(() {
mockYumemiWeather = MockYumemiWeather();
container = ProviderContainer(
overrides: [
weatherProvider.overrideWithValue(
Weather(client: mockYumemiWeather),
),
],
);
});

tearDown(() {
container.dispose();
});

group('天気情報取得のテスト', () {
test(
'天気情報取得に成功_正常なレスポンスを返した場合',
() async {
// Given
when(
mockYumemiWeather.fetchWeather(any),
).thenReturn(
'''
{
"weather_condition": "sunny",
"max_temperature": 30,
"min_temperature": 20,
"date": "2020-04-01T12:00:00+09:00"
}
''',
);

// When
final response = container.read(weatherProvider).fetch(request);

const expectedResponse = WeatherResponse(
weatherCondition: WeatherCondition.sunny,
maxTemperature: 30,
minTemperature: 20,
);

// Verify
expect(
response,
isA<Success<WeatherResponse, AppException>>().having(
(success) => success.value,
'expected WeatherResponse',
expectedResponse,
),
);
},
);

test('天気情報取得に失敗_APIがInvalidParameter返した場合', () async {
when(
mockYumemiWeather.fetchWeather(any),
).thenThrow(YumemiWeatherError.invalidParameter);

// When
final response = container.read(weatherProvider).fetch(request);

const expectedResponse = InvalidParameter();

// Then
expect(
response,
isA<Failure<WeatherResponse, AppException>>().having(
(failure) => failure.exception,
'AppException',
expectedResponse,
),
);
});

test('天気情報取得に失敗_APIが不明なエラーを返した場合', () async {
when(
mockYumemiWeather.fetchWeather(any),
).thenThrow(YumemiWeatherError.unknown);

// When
final response = container.read(weatherProvider).fetch(request);

const expectedResponse = UnknownWeather();

// Then
expect(
response,
isA<Failure<WeatherResponse, AppException>>().having(
(failure) => failure.exception,
'AppException',
expectedResponse,
),
);
});

test('天気情報取得に失敗_APIがアプリ側未定義の天気を返した場合', () async {
when(
mockYumemiWeather.fetchWeather(any),
).thenReturn('''
{
"weather_condition": "dummy",
"max_temperature": 30,
"min_temperature": 20,
"date": "2020-04-01T12:00:00+09:00"
}
''');

// When
final response = container.read(weatherProvider).fetch(request);

const expectedResponse = ResponseFormatException();

// Then
expect(
response,
isA<Failure<WeatherResponse, AppException>>().having(
(failure) => failure.exception,
'AppException',
expectedResponse,
),
);
});
});
}
114 changes: 114 additions & 0 deletions test/weather_test.mocks.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Mocks generated by Mockito 5.4.4 from annotations
// in flutter_training/test/weather_test.dart.
// Do not manually edit this file.

// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:mockito/mockito.dart' as _i1;
import 'package:mockito/src/dummies.dart' as _i3;
import 'package:yumemi_weather/src/yumemi_weather_base.dart' as _i2;

// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
// ignore_for_file: avoid_setters_without_getters
// ignore_for_file: comment_references
// ignore_for_file: deprecated_member_use
// ignore_for_file: deprecated_member_use_from_same_package
// ignore_for_file: implementation_imports
// ignore_for_file: invalid_use_of_visible_for_testing_member
// ignore_for_file: prefer_const_constructors
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class

/// A class which mocks [YumemiWeather].
///
/// See the documentation for Mockito's code generation for more information.
class MockYumemiWeather extends _i1.Mock implements _i2.YumemiWeather {
@override
String fetchSimpleWeather() => (super.noSuchMethod(
Invocation.method(
#fetchSimpleWeather,
[],
),
returnValue: _i3.dummyValue<String>(
this,
Invocation.method(
#fetchSimpleWeather,
[],
),
),
returnValueForMissingStub: _i3.dummyValue<String>(
this,
Invocation.method(
#fetchSimpleWeather,
[],
),
),
) as String);

@override
String fetchThrowsWeather(String? area) => (super.noSuchMethod(
Invocation.method(
#fetchThrowsWeather,
[area],
),
returnValue: _i3.dummyValue<String>(
this,
Invocation.method(
#fetchThrowsWeather,
[area],
),
),
returnValueForMissingStub: _i3.dummyValue<String>(
this,
Invocation.method(
#fetchThrowsWeather,
[area],
),
),
) as String);

@override
String fetchWeather(String? jsonString) => (super.noSuchMethod(
Invocation.method(
#fetchWeather,
[jsonString],
),
returnValue: _i3.dummyValue<String>(
this,
Invocation.method(
#fetchWeather,
[jsonString],
),
),
returnValueForMissingStub: _i3.dummyValue<String>(
this,
Invocation.method(
#fetchWeather,
[jsonString],
),
),
) as String);

@override
String syncFetchWeather(String? jsonString) => (super.noSuchMethod(
Invocation.method(
#syncFetchWeather,
[jsonString],
),
returnValue: _i3.dummyValue<String>(
this,
Invocation.method(
#syncFetchWeather,
[jsonString],
),
),
returnValueForMissingStub: _i3.dummyValue<String>(
this,
Invocation.method(
#syncFetchWeather,
[jsonString],
),
),
) as String);
}

0 comments on commit 57b4da8

Please sign in to comment.