2016-01-20 2 views
3

Можно ли издеваться над приложениями NSBundle, чтобы вернуть прогнозируемые результаты во время TDD?Mocking NSBundle in Swift TDD

Например:

Я хочу, чтобы проверить, что мое приложение обрабатывает, когда файл не сохраняется в NSBundle:

//Method to test 
func getProfileImage() -> UIImage { 
    if let profileImagePath = getProfilePhotoPath() { 
     UIImage(contentsOfFile: profileImagePath) 
    } 
    return UIImage(named: "defaultProfileImage") 
} 

private func getProfilePhotoPath() -> String? { 
    return NSBundle.mainBundle().pathForResource("profileImage", ofType: "png") 
} 

Можно ли дразнить NSBundle.mainBundle(), чтобы вернуть ложь для pathForResource?

ответ

4

В-третьих, NSBundle.mainBundle() - это жестко закодированная зависимость. Нам нужна возможность указать любой комплект, возможно, с mainBundle по умолчанию. Ответ Dependency Injection. Давайте использовать предпочтительную форму Конструктора инъекций, и воспользоваться параметрами Свифта по умолчанию:

class ProfileImageGetter { 
    private var bundle: NSBundle 

    init(bundle: NSBundle = NSBundle.mainBundle()) { 
     self.bundle = bundle 
    } 

    func getProfileImage() -> UIImage { 
     if let profileImagePath = getProfilePhotoPath() { 
      return UIImage(contentsOfFile: profileImagePath)! 
     } 
     return UIImage(named: "defaultProfileImage")! 
    } 

    private func getProfilePhotoPath() -> String? { 
     return bundle.pathForResource("profileImage", ofType: "png") 
    } 
} 

Теперь тест может создать экземпляр ProfileImageGetter и указать любой сверток он любит. Это может быть тестовый комплект или подделка.

Задание тестового комплекта позволит вам иметь ситуацию, когда profileImage.png не существует.

Задание подделки позволит вам заглушить результат вызова pathForResource().