Skip to content

Commit 83a9ed3

Browse files
committed
Added tests to viewModel for cached items
1 parent 8194ff3 commit 83a9ed3

File tree

1 file changed

+86
-13
lines changed

1 file changed

+86
-13
lines changed

ExampleMVVMTests/Presentation/MoviesScene/MoviesListViewModelTests.swift

Lines changed: 86 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class MoviesListViewModelTests: XCTestCase {
1616
}()
1717

1818
class SearchMoviesUseCaseMock: SearchMoviesUseCase {
19-
var executeCallCount: Int = 0
19+
var callCount: Int = 0
2020

2121
typealias ExecuteBlock = (
2222
SearchMoviesUseCaseRequestValue,
@@ -33,13 +33,13 @@ class MoviesListViewModelTests: XCTestCase {
3333
cached: @escaping (MoviesPage) -> Void,
3434
completion: @escaping (Result<MoviesPage, Error>) -> Void
3535
) -> Cancellable? {
36-
executeCallCount += 1
36+
callCount += 1
3737
_execute(requestValue, cached, completion)
3838
return nil
3939
}
4040
}
4141

42-
func test_whenFetchUsersUseCaseRetrievesEmptyPage_thenViewModelIsEmpty() {
42+
func test_whenSearchMoviesUseCaseRetrievesEmptyPage_thenViewModelIsEmpty() {
4343
// given
4444
let searchMoviesUseCaseMock = SearchMoviesUseCaseMock()
4545

@@ -58,7 +58,7 @@ class MoviesListViewModelTests: XCTestCase {
5858
XCTAssertEqual(viewModel.currentPage, 1)
5959
XCTAssertFalse(viewModel.hasMorePages)
6060
XCTAssertTrue(viewModel.items.value.isEmpty)
61-
XCTAssertEqual(searchMoviesUseCaseMock.executeCallCount, 1)
61+
XCTAssertEqual(searchMoviesUseCaseMock.callCount, 1)
6262
}
6363

6464
func test_whenSearchMoviesUseCaseRetrievesFirstPage_thenViewModelContainsOnlyFirstPage() {
@@ -77,13 +77,13 @@ class MoviesListViewModelTests: XCTestCase {
7777
viewModel.didSearch(query: "query")
7878

7979
// then
80-
let expectedItems: [MoviesListItemViewModel] = moviesPages[0]
80+
let expectedItems = moviesPages[0]
8181
.movies
8282
.map { MoviesListItemViewModel(movie: $0) }
8383
XCTAssertEqual(viewModel.items.value, expectedItems)
8484
XCTAssertEqual(viewModel.currentPage, 1)
8585
XCTAssertTrue(viewModel.hasMorePages)
86-
XCTAssertEqual(searchMoviesUseCaseMock.executeCallCount, 1)
86+
XCTAssertEqual(searchMoviesUseCaseMock.callCount, 1)
8787
}
8888

8989
func test_whenSearchMoviesUseCaseRetrievesFirstAndSecondPage_thenViewModelContainsTwoPages() {
@@ -99,9 +99,8 @@ class MoviesListViewModelTests: XCTestCase {
9999
)
100100
// when
101101
viewModel.didSearch(query: "query")
102-
XCTAssertEqual(searchMoviesUseCaseMock.executeCallCount, 1)
102+
XCTAssertEqual(searchMoviesUseCaseMock.callCount, 1)
103103

104-
let testPage2 = 1
105104
searchMoviesUseCaseMock._execute = { requestValue, _, completion in
106105
XCTAssertEqual(requestValue.page, 2)
107106
completion(.success(self.moviesPages[1]))
@@ -110,13 +109,13 @@ class MoviesListViewModelTests: XCTestCase {
110109
viewModel.didLoadNextPage()
111110

112111
// then
113-
let expectedItems: [MoviesListItemViewModel] = moviesPages
112+
let expectedItems = moviesPages
114113
.flatMap { $0.movies }
115114
.map { MoviesListItemViewModel(movie: $0) }
116115
XCTAssertEqual(viewModel.items.value, expectedItems)
117116
XCTAssertEqual(viewModel.currentPage, 2)
118117
XCTAssertFalse(viewModel.hasMorePages)
119-
XCTAssertEqual(searchMoviesUseCaseMock.executeCallCount, 2)
118+
XCTAssertEqual(searchMoviesUseCaseMock.callCount, 2)
120119
}
121120

122121
func test_whenSearchMoviesUseCaseReturnsError_thenViewModelContainsError() {
@@ -136,7 +135,7 @@ class MoviesListViewModelTests: XCTestCase {
136135
// then
137136
XCTAssertNotNil(viewModel.error)
138137
XCTAssertTrue(viewModel.items.value.isEmpty)
139-
XCTAssertEqual(searchMoviesUseCaseMock.executeCallCount, 1)
138+
XCTAssertEqual(searchMoviesUseCaseMock.callCount, 1)
140139
}
141140

142141
func test_whenLastPage_thenHasNoPageIsTrue() {
@@ -151,7 +150,7 @@ class MoviesListViewModelTests: XCTestCase {
151150
)
152151
// when
153152
viewModel.didSearch(query: "query")
154-
XCTAssertEqual(searchMoviesUseCaseMock.executeCallCount, 1)
153+
XCTAssertEqual(searchMoviesUseCaseMock.callCount, 1)
155154

156155
searchMoviesUseCaseMock._execute = { requestValue, _, completion in
157156
XCTAssertEqual(requestValue.page, 2)
@@ -163,10 +162,84 @@ class MoviesListViewModelTests: XCTestCase {
163162
// then
164163
XCTAssertEqual(viewModel.currentPage, 2)
165164
XCTAssertFalse(viewModel.hasMorePages)
166-
XCTAssertEqual(searchMoviesUseCaseMock.executeCallCount, 2)
165+
XCTAssertEqual(searchMoviesUseCaseMock.callCount, 2)
167166
}
168167

168+
func test_whenSearchMoviesUseCaseReturnsCachedData_thenViewModelShowsFirstCachedDataAndAfterFreshData() {
169+
// given
170+
let cachedPage: MoviesPage = .init(
171+
page: 1,
172+
totalPages: 2,
173+
movies: [.stub(id: "cachedMovieId1")]
174+
)
175+
let searchMoviesUseCaseMock = SearchMoviesUseCaseMock()
176+
177+
let viewModel = DefaultMoviesListViewModel(
178+
searchMoviesUseCase: searchMoviesUseCaseMock,
179+
mainQueue: DispatchQueueTypeMock()
180+
)
181+
182+
let testItemsBeforeFreshData = {
183+
let expectedItems = cachedPage
184+
.movies
185+
.map { MoviesListItemViewModel(movie: $0) }
186+
187+
XCTAssertEqual(viewModel.items.value, expectedItems)
188+
}
189+
190+
searchMoviesUseCaseMock._execute = { requestValue, cached, completion in
191+
XCTAssertEqual(requestValue.page, 1)
192+
cached(cachedPage)
193+
testItemsBeforeFreshData()
194+
completion(.success(self.moviesPages[0]))
195+
}
196+
197+
// when
198+
viewModel.didSearch(query: "query")
199+
200+
// then
201+
let expectedItems = moviesPages[0]
202+
.movies
203+
.map { MoviesListItemViewModel(movie: $0) }
204+
XCTAssertEqual(viewModel.items.value, expectedItems)
205+
XCTAssertEqual(viewModel.currentPage, 1)
206+
XCTAssertTrue(viewModel.hasMorePages)
207+
XCTAssertEqual(searchMoviesUseCaseMock.callCount, 1)
208+
}
169209

210+
func test_whenSearchMoviesUseCaseReturnsError_thenViewModelShowsCachedData() {
211+
// given
212+
let cachedPage: MoviesPage = .init(
213+
page: 1,
214+
totalPages: 2,
215+
movies: [.stub(id: "cachedMovieId1")]
216+
)
217+
let searchMoviesUseCaseMock = SearchMoviesUseCaseMock()
218+
219+
let viewModel = DefaultMoviesListViewModel(
220+
searchMoviesUseCase: searchMoviesUseCaseMock,
221+
mainQueue: DispatchQueueTypeMock()
222+
)
223+
224+
searchMoviesUseCaseMock._execute = { requestValue, cached, completion in
225+
XCTAssertEqual(requestValue.page, 1)
226+
cached(cachedPage)
227+
completion(.failure(SearchMoviesUseCaseError.someError))
228+
}
229+
230+
// when
231+
viewModel.didSearch(query: "query")
232+
233+
// then
234+
let expectedItems = cachedPage
235+
.movies
236+
.map { MoviesListItemViewModel(movie: $0) }
237+
XCTAssertEqual(viewModel.items.value, expectedItems)
238+
XCTAssertEqual(viewModel.currentPage, 1)
239+
XCTAssertTrue(viewModel.hasMorePages)
240+
XCTAssertEqual(searchMoviesUseCaseMock.callCount, 1)
241+
}
242+
170243
}
171244

172245
extension DefaultMoviesListViewModel {

0 commit comments

Comments
 (0)