Last active
July 14, 2019 20:32
-
-
Save rpassis/a123a397173dcd8b95a811147f38a4cd to your computer and use it in GitHub Desktop.
Unit testing memory leaks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// DeallocationSentinel.swift | |
// | |
// Created by Rogerio de Paula Assis on 7/14/19. | |
// Extracted from this CCH Melbourne talk: https://www.youtube.com/watch?v=514rJ1efv84 | |
// | |
public func expectDeallocation( | |
of object: AnyObject, | |
using deallocationExpectations: inout [XCTestExpectation] | |
) { | |
let expectation = XCTestExpectation(description: "Object \(object) deallocated") | |
objc_setAssociatedObject( | |
object, | |
&deallocatedExpectationKey, | |
DeallocationSentinel(deallocClosure: expectation.fulfill), | |
.OBJC_ASSOCIATION_RETAIN | |
) | |
deallocationExpectations.append(expectation) | |
} | |
// MARK: Private | |
private var deallocatedExpectationKey = 0 | |
private final class DeallocationSentinel { | |
private let deallocClosure: () -> Void | |
init(deallocClosure: @escaping () -> Void) { | |
self.deallocClosure = deallocClosure | |
} | |
deinit { | |
deallocClosure() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// DeallocTests.swift | |
// | |
// Created by Rogerio de Paula Assis on 7/14/19. | |
// Extracted from this CCH Melbourne talk: https://www.youtube.com/watch?v=514rJ1efv84 | |
// | |
import XCTest | |
class DeallocTests: XCTestCase { | |
private var deallocationExpectations: [XCTestExpectation] = [] | |
var subject: ViewModel! | |
override func setUp() { | |
subject = ViewModel() | |
let vc = ViewController(viewModel: subject) | |
subject.vc = vc | |
expectDeallocation(of: subject, using: deallocationExpectations) | |
} | |
override func tearDown() { | |
wait(for: self.deallocatioExpectations, timeout: 1) | |
} | |
func testDeallocation() { | |
XCTAssert(subject != nil) | |
subject = nil | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Dummy classes created to simulate a retain cycle for the test case above | |
// Add/remove weak from view model to verify different test result | |
class ViewModel { | |
/* weak */ var vc: ViewController? | |
} | |
class ViewController: UIViewController { | |
let viewModel: ViewModel | |
init(viewModel :ViewModel) { | |
self.viewModel = viewModel | |
super.init(nibName: nil, bundle: nil) | |
} | |
required init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment