8

So I created a custom an abstract class who inherit from UIViewController (Inherited by RebloodViewController) class named MainViewController. In this class I write a reusable nib registration function

class MainViewController: RebloodViewController {

    typealias Cell = RebloodViewController.Constants.Cell

    internal func registerNib(_ cellNib: Cell.Nib, target: UICollectionView) {

        let nib = UINib(nibName: cellNib.rawValue, bundle: nil)

        do {
            let identifier = try getCellIdentifierByNib(cellNib)
            target.register(nib, forCellWithReuseIdentifier: identifier)
        } catch {
            fatalError("Cell identifier not found from given nib")
        }
    }

    private func getCellIdentifierByNib(_ nib: Cell.Nib) throws -> String {

        var identifier: String? = nil

        switch nib {
        case .articles:
            identifier = Cell.Identifier.articles.rawValue
        case .events:
            identifier = Cell.Identifier.events.rawValue
        }

        guard let CellIdentifier = identifier else {
            throw MainError.cellIdentifierNotFound
        }

        return CellIdentifier
    }

}

What is the best way to unit test these private and internal function? Because I can't access the functions from the test files.

Putra
  • 399
  • 9
  • 23
  • It is explained in the answer of this question https://stackoverflow.com/questions/48208241/testing-a-class-which-preserves-its-state-in-private-variables – Umair Aamir Jan 17 '18 at 08:38

2 Answers2

12

You will not be able to test the private functions. But you can test internal ones. In your test, where you import your framework, eg import MyFramework, change it to:

@testable import MyFramework
totiDev
  • 5,189
  • 3
  • 30
  • 30
  • It seems like I can't import my custom class `MainViewController` with `@testable import MainViewController` it returns ```No such module 'MainViewController'``` – Putra Jan 17 '18 at 08:38
  • 2
    If you are using '@testable import MainViewController' then that is not correct. You need to use the name of the Framework you are testing against. Usually your test project contains this name, it may be MyAmazingAppTests, for a project called MyAmazingApp. The framework name would be 'MyAmazingApp' – totiDev Jan 17 '18 at 08:39
  • Got it. Thanks @totiG – Putra Jan 17 '18 at 08:45
1

I found the answer is we don't test private methods. We put a method private for a reason and it should be used by a public method. I assume whether we test private method, it's better to test the public method that uses the private method.

Another extra explanation I found it here: https://cocoacasts.com/how-to-unit-test-private-methods-in-swift/

Putra
  • 399
  • 9
  • 23