Skip to content

Commit

Permalink
Merge pull request #17 from wednesday-solutions/domain-unit-test
Browse files Browse the repository at this point in the history
Add domain unit tests
  • Loading branch information
shounak-mulay authored Mar 15, 2022
2 parents 444014a + a7cc175 commit bae84a8
Show file tree
Hide file tree
Showing 19 changed files with 309 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'package:flutter_template/domain/weather/get_favorite_cities_stream_use_case.dart';
import 'package:flutter_template/domain/weather/get_favorite_cities_stream_use_case_impl.dart';
import 'package:flutter_template/foundation/unit.dart';
import 'package:flutter_template/repository/weather/weather_repository.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';

import '../../exception/test_exceptions.dart';
import '../../extensions/stream_extensions.dart';
import '../../mocks/mocks.dart';
import '../../test_models/city_models.dart';

void main() {
late WeatherRepository weatherRepository;
late GetFavoriteCitiesStreamUseCase getFavoriteCitiesStreamUseCase;

setUp(() {
weatherRepository = MockWeatherRepository();
getFavoriteCitiesStreamUseCase = GetFavoriteCitiesStreamUseCaseImpl(
weatherRepository: weatherRepository);
});

tearDown(() {
resetMocktailState();
});

test(
"Given get favorite cities stream use case called, When no error occurs, Then correct data is emitted",
() {
// Given
final testCityList = singleCityList;
when(() => weatherRepository.getFavoriteCitiesStream())
.thenAnswer((invocation) => Stream.value(testCityList));

// When
expect(
getFavoriteCitiesStreamUseCase(unit),
// Then
emitsInOrder([testCityList]),
);
},
);

test(
"Given get favorite cities stream use case called, When error occurs, Then no data is emitted",
() {
// Given
final testException = TestException();
when(() => weatherRepository.getFavoriteCitiesStream())
.thenAnswer((invocation) => Stream.error(testException));

// When
getFavoriteCitiesStreamUseCase(unit)
// Then
.emitsNothing;
},
);
}
61 changes: 61 additions & 0 deletions test/domain/weather/set_city_favorite_use_case_impl_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:flutter_template/domain/entity/base/result/result.dart';
import 'package:flutter_template/domain/weather/set_city_favorite_use_case_impl.dart';
import 'package:flutter_template/repository/weather/weather_repository.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';

import '../../exception/test_exceptions.dart';
import '../../extensions/mock_extensions.dart';
import '../../mocks/mocks.dart';
import '../../test_models/city_models.dart';

void main() {
late WeatherRepository weatherRepository;
late SetCityFavoriteUseCaseImpl setCityFavoriteUseCase;

setUp(() {
weatherRepository = MockWeatherRepository();
setCityFavoriteUseCase = SetCityFavoriteUseCaseImpl(
weatherRepository: weatherRepository,
);
});

tearDown(() {
resetMocktailState();
});

test(
"Given set city favorite use case is called, When no error occurs, Then Result.success is returned",
() async {
// Given
final testCity = city1;
when(() => weatherRepository.setCityAsFavorite(testCity)).justRun();

// When
final result = await setCityFavoriteUseCase(param: testCity);

// Then
expect(result, isA<Success>());
verify(() => weatherRepository.setCityAsFavorite(testCity)).called(1);
},
);

test(
"Given set city favorite use case is called, When error occurs, Then Result.failure is returned",
() async {
// Given
final testCity = city1;
final testException = TestException();
when(() => weatherRepository.setCityAsFavorite(testCity))
.thenThrow(testException);

// When
final result = await setCityFavoriteUseCase(param: testCity);

// Then
expect(result, isA<Error>());
expect((result as Error).exception, same(testException));
verify(() => weatherRepository.setCityAsFavorite(testCity)).called(1);
},
);
}
2 changes: 2 additions & 0 deletions test/extensions/stream_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ extension StreamEmitsInOrderExt<T> on Stream<T> {
void inOrder(Iterable matchers) {
expect(this, emitsInOrder(matchers));
}

get emitsNothing => expect(this, neverEmits(isA<Object?>()));
}
3 changes: 3 additions & 0 deletions test/mocks/mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:flutter_template/repository/weather/domain_weather_mapper.dart';
import 'package:flutter_template/repository/weather/local_city_mapper.dart';
import 'package:flutter_template/repository/weather/local_day_weather_mapper.dart';
import 'package:flutter_template/repository/weather/local_weather_mapper.dart';
import 'package:flutter_template/repository/weather/weather_repository.dart';
import 'package:flutter_template/services/weather/local/weather_local_service.dart';
import 'package:flutter_template/services/weather/remote/weather_remote_service.dart';
import 'package:mocktail/mocktail.dart';
Expand All @@ -30,6 +31,8 @@ class MockLocalDayWeatherMapper extends Mock implements LocalDayWeatherMapper {}
// Repositories
class MockDateRepository extends Mock implements DateRepository {}

class MockWeatherRepository extends Mock implements WeatherRepository {}

// Interactors
class MockFavoriteWeatherInteractor extends Mock
implements FavoriteWeatherInteractor {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import '../../../../../extensions/mock_extensions.dart';
import '../../../../../extensions/stream_extensions.dart';
import '../../../../../mocks/mocks.dart';
import '../../../../base/test_helpers.dart';
import '../models/ui_city_models.dart';
import '../../../../../test_models/ui_city_models.dart';

void main() {
late SearchNavigator searchNavigator;
Expand Down
101 changes: 101 additions & 0 deletions test/repository/weather/domain_city_mapper_impl_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import 'package:collection/collection.dart';
import 'package:flutter_template/domain/entity/weather/city.dart';
import 'package:flutter_template/repository/weather/domain_city_mapper.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';

import '../../test_models/city_models.dart';
import '../../test_models/local_city_data_models.dart';
import '../../test_models/remote_city_models.dart';

void main() {
late DomainCityMapper domainCityMapper;

setUp(() {
domainCityMapper = DomainCityMapperImpl();
});

tearDown(() {
resetMocktailState();
});

test(
"Given local city data, When map called, Then city is returned",
() {
// Given
final localCityData = localCityData1;
final city = city1;

// When
final result = domainCityMapper.map(localCityData);

// Then
expect(result, isA<City>());
expect(result.title, city.title);
expect(result.location, city.location);
expect(result.id, city.id);
expect(result.locationType, city.locationType);
},
);

test(
"Given local city data list, When map list called, Then city list is returned",
() {
// Given
final localCityData = allLocalCityDataList;
final cityList = allCityList;

// When
final result = domainCityMapper.mapList(localCityData);

// Then
expect(result, isA<List<City>>());
result.forEachIndexed((index, city) {
expect(city.title, cityList[index].title);
expect(city.location, cityList[index].location);
expect(city.id, cityList[index].id);
expect(city.locationType, cityList[index].locationType);
});
},
);

test(
"Given remote city, When map remote city called, Then city is returned",
() {
// Given
const remoteCityData = remoteCity1;
final city = city1;

// When
final result = domainCityMapper.mapRemoteCity(remoteCityData);

// Then
expect(result, isA<City>());
expect(result.title, city.title);
expect(result.location, city.location);
expect(result.id, city.id);
expect(result.locationType, city.locationType);
},
);

test(
"Given local city data list, When map list called, Then city list is returned",
() {
// Given
const remoteCityList = allRemoteCityList;
final cityList = allCityList;

// When
final result = domainCityMapper.mapRemoteCityList(remoteCityList);

// Then
expect(result, isA<List<City>>());
result.forEachIndexed((index, city) {
expect(city.title, cityList[index].title);
expect(city.location, cityList[index].location);
expect(city.id, cityList[index].id);
expect(city.locationType, cityList[index].locationType);
});
},
);
}
10 changes: 0 additions & 10 deletions test/repository/weather/models/city_models.dart

This file was deleted.

10 changes: 0 additions & 10 deletions test/repository/weather/models/local_city_data_models.dart

This file was deleted.

30 changes: 15 additions & 15 deletions test/repository/weather/weather_repository_impl_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import 'package:mocktail/mocktail.dart';

import '../../exception/test_exceptions.dart';
import '../../mocks/mocks.dart';
import 'models/city_models.dart';
import 'models/local_city_data_models.dart';
import 'models/local_city_with_weather_models.dart';
import 'models/local_day_weather_companion.dart';
import 'models/local_day_weather_models.dart';
import 'models/local_weather_companion_models.dart';
import 'models/remote_weather_models.dart';
import 'models/weather_models.dart';
import '../../test_models/city_models.dart';
import '../../test_models/local_city_data_models.dart';
import '../../test_models/local_city_with_weather_models.dart';
import '../../test_models/local_day_weather_companion.dart';
import '../../test_models/local_day_weather_models.dart';
import '../../test_models/local_weather_companion_models.dart';
import '../../test_models/remote_weather_models.dart';
import '../../test_models/weather_models.dart';

void main() {
late WeatherLocalService weatherLocalService;
Expand Down Expand Up @@ -65,8 +65,8 @@ void main() {
"Given local service returns list of LocalCityData, When getFavoriteCitiesList is called, Then Future<List<City>> is returned",
() async {
// Given
final localCityData = localCityDataList;
final cityData = cityList;
final localCityData = singleLocalCityDataList;
final cityData = singleCityList;
when(() => weatherLocalService.getFavouriteCities())
.thenAnswer((_) => Future.value(localCityData));
when(() => domainCityMapper.mapList(localCityData)).thenReturn(cityData);
Expand Down Expand Up @@ -104,8 +104,8 @@ void main() {
"Given local services returns stream of local city data, When getFavoriteCitiesStream is called, then Stream<List<City>> is returned",
() {
// Given
final localCityData = localCityDataList;
final cityData = cityList;
final localCityData = singleLocalCityDataList;
final cityData = singleCityList;
when(() => weatherLocalService.getFavoriteCitiesStream())
.thenAnswer((_) => Stream.value(localCityData));
when(() => domainCityMapper.mapList(localCityData)).thenReturn(cityData);
Expand Down Expand Up @@ -218,7 +218,7 @@ void main() {
() async {
// Given
const date = Date(year: 1970, month: 1, day: 1);
final localCityData = localCityDataList;
final localCityData = singleLocalCityDataList;
final localCity = localCityData.first;
final remoteWeatherData = remoteWeather;
const localWeatherCompanionData = localWeatherCompanion;
Expand Down Expand Up @@ -271,7 +271,7 @@ void main() {
// Given
const date = Date(year: 1970, month: 1, day: 1);
const nowDate = Date(year: 2021, month: 1, day: 31);
final localCityData = localCityDataList;
final localCityData = singleLocalCityDataList;
final localCity = localCityData.first;
final remoteWeatherData = remoteWeather;
const localWeatherCompanionData = localWeatherCompanion;
Expand Down Expand Up @@ -324,7 +324,7 @@ void main() {
() async {
// Given
const date = Date(year: 1970, month: 1, day: 1);
final localCityData = localCityDataList;
final localCityData = singleLocalCityDataList;
final localCity = localCityData.first;
const localWeatherCompanionData = localWeatherCompanion;
final localDayWeatherCompanionData = localDayWeatherCompanionList;
Expand Down
24 changes: 24 additions & 0 deletions test/test_models/city_models.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:flutter_template/domain/entity/weather/city.dart';

final singleCityList = [
city1,
];

final allCityList = [
city1,
city2,
];

final city1 = City(
id: 1,
title: "title 1",
locationType: "locationType 1",
location: "location 1",
);

final city2 = City(
id: 2,
title: "title 2",
locationType: "locationType 2",
location: "location 2",
);
Loading

0 comments on commit bae84a8

Please sign in to comment.