3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

テストダブル:Spy編

Posted at

UITableView.reloadData()を呼んでることのテストの例

テストできない例

ViewControllerの役割:

  • repoが値を返した時にtableView.reloadDataを実行する ← このままだとテストできない

ViewController

class ToDoListViewController: UIViewController {
    private var toDoItems: [ToDoItem] = []
    private var toDoListRepo: ToDoListRepository

	init(toDoListRepo: ToDoListRepository) {
		self.toDoListRepo = toDoListRepo
	}

    override func viewDidLoad() {
        super.viewDidLoad()
        toDoListRepo
            .getAll()
			.onSuccess { toDoItems in
                self.toDoItems = toDoItems
                self.tableView.reloadData() //<- これを呼んでることのテストができない
            }
    }
}

テストできる例

ViewControllerの役割をちょっと変える。あと新しい登場人物を追加する

Reloaderの役割:

  • reloadメソッドの引数として、”reloadDataメソッドを持っている何か”(Reloadableに準拠したクラス)を受け取る
  • 受け取った”reloadDataメソッドを持ってる何か”のreloadDataメソッドを実行する

ViewControllerの役割:

  • “reloadメソッドを持ってる何か”(Reloaderに準拠したクラス)のreloadを実行する
  • reloadDataの引数にtableViewを渡す

Reloadableたち
SpyReloadableもUITableViewも、reloadDataを持っているという共通点があることを保証する

protocol Reloadable {
    func reloadData()
}

//Reloadableに準拠させる
class SpyReloadable: Reloadable {
	//reloadDataが呼ばれたらtrueになる、呼ばれなかったらfalseのまま
    private(set) var reloadData_wasCalled: Bool = false
    func reloadData() {
        reloadData_wasCalled = true
    }
}

//Reloadableに準拠させる
//UITableViewはreloadDataメソッドを持っているので準拠させれる
extension UITableView: Reloadable {}

Reloaderたち
SpyReloaderもDefaultReloaderも、reloadを持っているという共通点があることを保証する

protocol Reloader {
    func reload(reloadable: Reloadable)
}

//Reloaderに準拠させる
class SpyReloader: Reloader {
    //reload実行時の引数(reloadable)に何を渡されたか覚えておく
    private(set) var reload_argument_reloadable: Reloadable? = nil

	//reloadDataメソッドを持ってればなんでもいい
    func reload(reloadable: Reloadable) { 
        reload_argument_reloadable = reloadable
    }
}

//Reloaderに準拠させる
class DefaultReloader: Reloader {
	//reloadDataメソッドを持ってればなんでもいい
    func reload(reloadable: Reloadable) { 
		//reloadDataメソッド実行する
        reloadable.reloadData()
    }
}

ViewController

class ToDoListViewController: UIViewController {
    private var toDoItems: [ToDoItem] = []
    private var toDoListRepo: ToDoListRepository
    private var reloader: Reloader //reloadメソッドを持ってればなんでもいい

		init(toDoListRepo: ToDoListRepository, reloader: Reloader) {
			self.toDoListRepo = toDoListRepo
	    	self.reloader = reloader
		}

    override func viewDidLoad() {
        super.viewDidLoad()
        toDoListRepo
            .getAll()
				.onSuccess { toDoItems in
                self.toDoItems = toDoItems

				//”reloadメソッドを持っている何か”のreloadメソッドに、
				//reloadDataメソッドを持っているtableViewを渡して実行する
                self.reloader.reload(reloadable: self.tableView)
            }
    }
}

テストコード(Quick、Nimble使用)

ViewControllerのテスト

it("reloads the tableview's data once the repository returns data") {
	stubToDoListRepository = StubToDoListRepository()
    stubToDoListRepository.getAll_returnPromise.success([])
	spyReloader = SpyReloader()

    toDoListTableViewController = ToDoListViewController(
		toDoListRepo: stubToDoListRepository,
        reloader: spyReloader  //実行時に引数として何を渡されたか覚えといてくれるやつを渡す
    )
    toDoListTableViewController.loadViewIfNeeded()
    
    
    //なにを渡されて実行されたかチェックする
    expect(spyReloader.reload_argument_reloadable).toEventually(beAKindOf(UITableView.self))
}

Reloaderのテスト

it("calls reload on the object that is passed in") {
	let defaultReloader = DefaultReloader()
    let spyReloadable = SpyReloadable()

    //実行されたか、されてないか覚えといてくれるやつを渡して実行する
    defaultReloader.reload(reloadable: spyReloadable)
    
    //渡したものが実行されてるか確認する
    expect(spyReloadable.reloadData_wasCalled).to(beTrue())
}
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?