我想为我的函数编写一个单元测试,这是代码:
func smartBack(animated: Bool = true) {
if isModal() {
self.dismiss(animated: animated, completion: nil)
} else {
self.navigationController?.popViewController(animated: animated)
}
}
此方法自动选择关闭或弹出。那么,如何检查此功能后是否弹出或关闭了viewcontroller?谢谢你的帮助
答案 0 :(得分:0)
您可以使用属性 self.isBeingPresented ,如果显示的是视图控制器,则将返回true;否则,如果按下则返回false。
答案 1 :(得分:0)
您可以使用以下方法检查viewControllers堆栈,并查看是否包含viewController:
self.navigationController.viewControllers
这将返回navigationController堆栈中包含的[UIViewController]
。
答案 2 :(得分:0)
您可以通过其for (const itm of item) {
console.log(itm)
}
或isBeingDismissed
函数检查视图控制器的viewWillAppear
属性。
请参见https://developer.apple.com/documentation/uikit/uiviewcontroller/2097562-isbeingdismissed。
答案 3 :(得分:0)
我个人会使用Mocks来跟踪何时调用某些方法。
您可以这样做:
class MockNavigationController: UINavigationController {
var _popCalled: Bool = false
override func popViewController(animated: Bool) -> UIViewController? {
_popCalled = true
return self.viewControllers.first
}
}
然后,无论何时您的代码调用popViewController,_popCalled
值都会被更新,但实际上不会弹出任何内容。因此,您可以断言_popCalled
的值,以确保发生了预期的呼叫。
这样可以很容易地测试是否发生了预期的事情,还使您无法在测试中运行实际的代码。此方法很容易进行服务调用或数据库更新,设置标志等,因此更加安全。
尽管一开始它们可能很难理解。我建议在大量使用之前先阅读它们。
操场上的完整示例:
import UIKit
import PlaygroundSupport
import MapKit
class ClassUnderTest: UIViewController {
var isModal: Bool = false
func smartBack(animated: Bool = true) {
if isModal {
self.dismiss(animated: animated, completion: nil)
} else {
self.navigationController?.popViewController(animated: animated)
}
}
}
class MockNavigationController: UINavigationController {
var _popCalled: Bool = false
override func popViewController(animated: Bool) -> UIViewController? {
_popCalled = true
return self.viewControllers.first
}
}
class MockClassUnderTest: ClassUnderTest {
var _mockNavigationController = MockNavigationController()
override var navigationController: UINavigationController? {
return _mockNavigationController
}
var _dismissCalled: Bool = false
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
_dismissCalled = true
}
}
var subject = MockClassUnderTest()
subject.isModal = true
subject.smartBack();
var navigation = subject.navigationController as! MockNavigationController
print(subject._dismissCalled)
print(navigation._popCalled)
输出:
true
false
subject = MockClassUnderTest();
subject.isModal = false
subject.smartBack();
navigation = subject.navigationController as! MockNavigationController
print(subject._dismissCalled)
print(navigation._popCalled)
输出:
false
true
在此示例中,您将覆盖在两种情况下都将调用的dismiss和pop方法。在单元测试中,您只需断言存根值(_popCalled)符合您的期望就可以。
答案 4 :(得分:0)
我以这种方式解决了。我需要测试一个包含以下内容的简单方法:dismiss(animated: true, completion: nil)
,并制作了一个临时模拟了一个模拟viewController的临时模拟程序,该程序对我的MainController进行了推送,在其中我应用了dismissView。
func testValidatesTheDismissOfViewController() {
// Given
let mockViewController: UIViewController = UIViewController()
let navigationController = UINavigationController(rootViewController: mockViewController)
// Create instance of my controller that is going to dismiss.
let sut: HomeWireFrame = HomeWireFrame().instanceController()
navigationController.presentFullScreen(sut, animated: true)
// When
sut.loadViewIfNeeded()
sut.closeView()
// Create an expectation...
let expectation = XCTestExpectation(description: "Dismiss modal view: HomeViewController")
// ...then fulfill it asynchronously
DispatchQueue.main.async { expectation.fulfill() }
wait(for: [expectation], timeout: 1)
// Then - if its different of my home controller
XCTAssertTrue(!(navigationController.topViewController is HomeViewController))
}
我希望能有所帮助,我在这里毫无疑问。
答案 5 :(得分:0)
func smartBack(动画:Bool = true)将是:
func smartBack(animated: Bool = true) {
if self.navigationController?.viewControllers.first == self {
self.dismiss(animated: animated, completion: nil)
} else {
self.navigationController?.popViewController(animated: true)
}
}