为何XCTestCase可选实例变量赋值后在另一测试方法中为nil?
为啥XCTest里测试方法间的实例变量不共享?
哈哈,这个坑我刚接触XCTest的时候也踩过!你遇到的问题核心原因是:XCTest框架会为每个测试方法创建一个全新的FooTests类实例。
也就是说:
- 执行
test_A_setFoo()时,框架新建了一个FooTests对象,你在这个对象里把foo设为1,测试自然通过; - 执行
test_B_fooIsNotNil()时,框架又新建了另一个完全独立的FooTests对象,这个对象的foo还是初始的nil,所以断言失败。
解决方法
根据你的需求,有几种常见的处理方式:
1. 使用setUp()初始化(每个测试方法都初始化一次)
如果每个测试方法都需要一个非nil的foo,可以在setUp()里赋值,这个方法会在每个测试方法执行前自动调用:
class FooTests: XCTestCase { var foo: Int? override func setUp() { super.setUp() foo = 1 // 每个测试实例都会执行这里的初始化 } func test_A_setFoo() { XCTAssertNotNil(foo) } func test_B_fooIsNotNil() { XCTAssertNotNil(foo) } }
2. 使用静态/类属性(跨测试方法共享状态)
如果你确实需要让foo在不同测试方法间保持状态,那就把它改成静态属性或者类属性,这样所有测试实例共享同一个变量:
class FooTests: XCTestCase { static var foo: Int? // 静态属性,所有实例共享 func test_A_setFoo() { XCTAssertNil(FooTests.foo) FooTests.foo = 1 XCTAssertNotNil(FooTests.foo) } func test_B_fooIsNotNil() { XCTAssertNotNil(FooTests.foo) } }
⚠️ 注意:这种方式要小心测试执行顺序!XCTest默认不会按代码顺序执行测试方法,除非你手动配置测试套件的执行顺序。如果你的测试逻辑依赖前一个测试的结果,很容易出问题,尽量避免这种强依赖的写法。
3. 合并相关测试(推荐)
如果这两个测试本来就是验证同一个流程的不同环节,更合理的做法是把它们合并成一个测试方法,避免依赖跨测试的状态:
class FooTests: XCTestCase { var foo: Int? func test_FooLifecycle() { // 第一步:初始状态是nil XCTAssertNil(foo) // 第二步:设置后非nil foo = 1 XCTAssertNotNil(foo) // 可以继续添加后续验证逻辑 } }
内容的提问来源于stack exchange,提问作者Peter Warbo
相关产品推荐
相关产品推荐

