使用 XCTAssertThrows 模拟进行 Swift 单元测试
Posted
技术标签:
【中文标题】使用 XCTAssertThrows 模拟进行 Swift 单元测试【英文标题】:Swift Unit testing with XCTAssertThrows analogue 【发布时间】:2014-06-05 06:05:49 【问题描述】:在 swift 语言单元测试中是否有任何等效的检查抛出异常的方法?
例如我有一堂课:
class Square : NSObject
let sideLength: Int
init(sideLength: Int)
assert(sideLength >= 0, "Wrong initialization of Square class with below zero side length")
self.sideLength = sideLength
super.init()
并测试以检查它是否有效。在目标 C 中,我可以编写这样的测试方法:
- (void)testInitializationWithWrongSideLengthThrowsExceptions
XCTAssertThrows([[Shape alloc] initWithSideLength: -50], "Should throw exceptions on wrong side values initialisations");
什么是 Swift 平等技术?
【问题讨论】:
@Vignesh Kumar:请完全停止重新标记 Swift 问题。你没有帮助。完全没有。 【参考方案1】:如果您将以下三个文件添加到您的测试中:
// ThrowsToBool.h
#import <Foundation/Foundation.h>
/// A 'pure' closure; has no arguments, returns nothing.
typedef void (^VoidBlock)(void);
/// Returns: true if the block throws an `NSException`, otherwise false
BOOL throwsToBool(VoidBlock block);
// ThrowsToBool.m
#import "ThrowsToBool.h"
BOOL throwsToBool(VoidBlock const block)
@try
block();
@catch (NSException * const notUsed)
return YES;
return NO;
// xxxTests-Bridging-Header.h
#import "ThrowsToBool.h"
然后你可以写:
XCTAssert(throwsToBool
// test code that throws an NSException
)
但它不适用于断言或前置条件:(
PS 我的想法来自:http://modocache.io/xctest-the-good-parts
【讨论】:
【参考方案2】:我认为assert()
-function 应该只用于调试目的。不仅是因为来自 Apple 的 Swift-Book (https://itun.es/de/jEUH0.l) 的以下声明:
“断言会导致您的应用终止,并且不能替代以不太可能出现无效条件的方式设计您的代码。”
这就是为什么我会这样解决这个问题:
import Cocoa
import XCTest
class Square
let sideLength: Int
init(_ sideLength: Int)
self.sideLength = sideLength >= 0 ? sideLength : 0
class SquareTests: XCTestCase
override func setUp() super.setUp()
override func tearDown() super.tearDown()
func testMySquareSideLength()
let square1 = Square(1);
XCTAssert(square1.sideLength == 1, "Sidelength should be 1")
let square2 = Square(-1);
XCTAssert(square2.sideLength >= 0, "Sidelength should be not negative")
let tester = SquareTests()
tester.testMySquareSideLength()
【讨论】:
【参考方案3】:swift 中没有与 XCTAssertThrows 等效的功能。现在你不能使用原生函数,但是有一个带有一些 Objective-C 帮助的解决方案。您可以使用 Quick,或仅使用 Nimble。或者制作自己的断言函数 - 参见这篇文章 - http://modocache.io/xctest-the-good-parts - 潜在改进 #2:将 XCTAssertThrows 添加到 Swift
【讨论】:
【参考方案4】:我认为最好的方法是添加一座桥。
请看https://gist.github.com/akolov/8894408226dab48d3021
它对我有用。
【讨论】:
【参考方案5】:Swift 2 中的正确方法:
class Square : NSObject
let sideLength: Int
init(sideLength: Int) throws // throwable initializer
guard sideLength >= 0 else // use guard statement
throw ...// your custom error type
self.sideLength = sideLength
super.init()
和测试:
func testInitThrows()
do
_ = try Square(sideLength: -1) // or without parameter name depending on Swift version
XCTFail()
catch ... // your custom error type
catch
XCTFail()
【讨论】:
以上是关于使用 XCTAssertThrows 模拟进行 Swift 单元测试的主要内容,如果未能解决你的问题,请参考以下文章