我正在研究如何对SwiftUI视图代码进行单元测试。
我有以下定义:
struct ContentView : View {
var body: some View {
Text("Hello World")
.font(.title)
.fontWeight(.bold)
}
}
我可以这样测试:
func testBody() {
let cv = ContentView()
let body = cv.body
XCTAssertNotNil(body)
guard let text = body as? Text else { XCTFail(); return }
XCTAssertEqual(Text("Hello World").font(.title).fontWeight(.bold), text)
}
但是,一旦我想测试文本对齐方式,就会遇到问题:
生产代码:
struct ContentView : View {
var body: some View {
Text("Hello World")
.font(.title)
.fontWeight(.bold)
.multilineTextAlignment(.leading)
}
}
和测试代码:
func testBody() {
let cv = ContentView()
let body = cv.body
XCTAssertNotNil(body)
guard let text = body as? Text else { XCTFail(); return }
// COMPILER ERROR ON NEXT LINE
XCTAssertEqual(Text("Hello World").font(.title).fontWeight(.bold).multilineTextAlignment(.leading), text)
}
...然后出现以下编译器错误:
Cannot convert value of type 'Text' to expected argument type '_ModifiedContent<Text, _EnvironmentKeyWritingModifier<HAlignment>>'
如何测试Text
结构的对齐方式?
答案 0 :(得分:2)
.font(_:)
有两个扩展名,即:
extension View {
/// Sets the default font for text in this view.
///
/// - Parameter font: The default font to use in this view.
/// - Returns: A view with the default font set to the value you supply.
public func font(_ font: Font?) -> Self.Modified<_EnvironmentKeyWritingModifier<Font?>>
}
和
extension Text {
/// Sets the font to use when displaying this text.
///
/// - Parameter font: The font to use when displaying this text.
/// - Returns: Text that uses the font you specify.
public func font(_ font: Font?) -> Text
}
在Text
结构上执行方法.font时,您将使用所应用的字体返回新的Text
,因为它调用了{{ 1}}(使用更具体的返回类型创建重载方法总是可以的)。例如,在font(_:)
上调用font方法时,返回类型为:
Button
好吧,这已经不再是普通的ModifiedContent<Button<Text>, _EnvironmentKeyWritingModifier<Font?>>
了,而是一个包装的非常复杂的类型,因为它没有像Text一样具有自身的重载,因此它调用了'normal'方法。
在Button
实例上调用multilineTextAlignment
时会发生什么?
Text
没有extension View {
/// Sets the alignment of multiline text in this view.
///
/// - Parameter alignment: A value you use to align lines of text to the
/// left, right, or center.
/// - Returns: A view that aligns the lines of multiline `Text` instances
/// it contains.
public func multilineTextAlignment(_ alignment: HAlignment) -> Self.Modified<_EnvironmentKeyWritingModifier<HAlignment>>
}
的重载,就像font方法的重载一样。这意味着返回类型不同于新的Text
实例。现在我们陷入了一个复杂的时间。
幸运的是,该复杂类型有一个Text
属性。执行此操作时,您的测试将编译:
content
否定了XCTAssertEqual(Text("Hello World").font(.title).fontWeight(.bold).multilineTextAlignment(.leading).content, text)
属性:)?
运行测试时,content
变量并非像您期望的那样是body
类型,但是具有另一个非常复杂的类型,这就是测试失败的原因。要通过测试,请执行以下操作:
Text
答案 1 :(得分:1)
您可以使用ViewInspector库对SwiftUI层次进行单元测试:
let view = ContentView()
let string = try view.inspect().text().string()
XCTAssertEqual(string, "Hello, world!")