The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

Monica_G (28) [Avatar] Offline

I am working on Chapter 15, section 7 "Testing Your App". I've cloned the "Chapter15.3.Tested" branch of the Bookcase app from github. When I run the "testSortTitle" test it fails. It fails because the BooksManager class calls the loadBooks() function on instantiation. So, the array is not empty. The first item is "Animal Farm", which the unit test is not expecting. It expects "Gulliver's Travels".

I got around this by creating a subclass of the BooksManager class in the unit test. It overrides the "retrieveBooks()" function to return an empty array.

Is this an appropriate approach to this type of problem? Is there another way to approach it?

Here is what I did:

import XCTest
@testable import Bookcase

class MockBooksManager: BooksManager {
  override func retrieveBooks() -> [Book]? {
    return []

class BooksManagerTests: XCTestCase {

    var booksManager:MockBooksManager!
    var bookDaVinci:Book!
    var bookGulliver:Book!
    var bookOdyssey:Book!

    override func setUp() {
        bookDaVinci = Book(title: "The Da Vinci Code", author: "Dan Brown", rating: 5, isbn: "", notes: "")
        bookGulliver = Book(title: "Gulliver's Travels", author: "Jonathan Swift", rating: 5, isbn: "", notes: "")
        bookOdyssey = Book(title: "The Odyssey", author: "Homer", rating: 5, isbn: "", notes: "")
        booksManager = MockBooksManager()
 // rest of unit test code snipped


Craig Grummitt (50) [Avatar] Offline
You're right, there was a late change to the book, to keep the test data in, to use it as an excuse to introduce the project in the first chapter. However the impact this would have on the tests here was overlooked.

I like your creative solution to subclass BooksManager and override the retrieveBooks method. The only concern I would have with subclassing the class is that with every change we make in a subclass we'll have a little less certainty that the original class passed the tests - i.e. the changes we made in the subclass could have resolved any issues in the original class. Admittedly this isn't so big a problem with one little change like you've made, but could be dangerous if we keep making changes in a subclass. I guess if you ensured that the mock class was coupled to the test, this would be ok.

An approach I was thinking of was to be sure the books array is empty, by setting up a reset method in the BooksManager:

func resetBooks() {
  books = []
  filteredBooks = []

And then we could call this method before adding books.