什么是Sourcery?Sourcery是最流行的Swift代码生成工具之一。它在其背后使用SwiftSyntax[1],旨在通过自动生成样板代码来节省开发人员的时间。Sourcery扫描一组输入文件,然后在模板的帮助下,自动生成模板中定义的Swift代码。示例考虑为相机会话服务提供公共API的协议:protocolCamera{funcstart()funcstop()funccapture(_completion:@escaping(UIImage?)->Void)funcrotate()}new在对Camera服务进行单元测试时,我们要确保AVCaptureSession并未实际创建。我们只是想确认被测系统(SUT)正确调用了摄像头服务,而不是测试摄像头服务本身。因此,创建协议的模拟实现是有意义的,使用一个空方法和一组变量来帮助我们进行单元测试,并断言(资产)进行了正确的调用。这是软件开发中非常常见的场景,如果您曾经维护过包含大量单元测试的大型代码库,那么它也可能会有点乏味。嗯~别担心!Sourcery将帮助您!??它有一个名为AutoMockable[2]的模板,它将为任何输入文件中符合AutoMockable协议的任何协议生成模拟实现。注意:在本文中,我广泛使用了模拟一词,因为它与Sourcery模板使用的术语一致。Mock是一个相当重载的术语,但通常,如果我要创建双重测试[3],我会根据它的用途进一步指定类型的名称(可能是Spy、Fake、Stub等)。如果您有兴趣了解有关双重测试的更多信息,MartinFowler有一篇非常好的文章解释了这些差异。现在,我们让Camera服从AutoMockable。此接口的唯一目的是充当源代码目标,从中查找和生成代码。importUIKit//要匹配的协议protocolAutoMockable{}publicprotocolCamera:AutoMockable{funcstart()funcstop()funccapture(_completion:@escaping(UIImage?)->Void)funcrotate()}此时,您可以在上述输入文件上运行Sourcery命令,指定AutoMockable模板的路径:sourcery--sourcesCamera.swift--templatesAutoMockable.stencil--output。本文通过提供.sourcery.yml文件来配置Sourcery插件。如果提供了配置文件或者Sourcery可以找到配置文件,任何与其值冲突的命令行参数都将被忽略。如果您想了解有关配置文件的更多信息,Sourcery的存储库中有一个涵盖该主题的部分[4]。命令执行后,会在输出目录下生成一个模板名,后缀为.generated.swift的文件。例如./AutoMockable.generated.swift://使用Sourcery1.8.2生成—https://github.com/krzysztofzablocki/Sourcery//请勿编辑//swiftlint:disableline_length//swiftlint:disablevariable_nameimportFoundation#if操作系统(iOS)||操作系统(电视操作系统)||os(watchOS)importUIKit#elseifos(OSX)importAppKit#endifclassCameraMock:Camera{//MARK:-开始varstartCallsCount=0varstartCalled:Bool{returnstartCallsCount>0}varstartClosure:(()->Void)?funcstart(){startCallsCount+=1startClosure?()}//MARK:-停止varstopCallsCount=0varstopCalled:Bool{returnstopCallsCount>0}varstopClosure:(()->Void)?funcstop(){stopCallsCount+=1stopClosure?()}//MARK:-捕获varcaptureCallsCount=0varcaptureCalled:Bool{returncaptureCallsCount>0}varcaptureReceivedCompletion:((UIImage?)->Void)?变量captureReceivedInvocations:[((UIImage?)->Void)]=[]varcaptureClosure:((@escaping(UIImage?)->Void)->Void)?funccapture(_completion:@escaping(UIImage?)->Void){captureCallsCount+=1captureReceivedCompletion=completioncaptureReceivedInvocations。append(completion)captureClosure?(completion)}//MARK:-旋转varrotateCallsCount=0varrotateCalled:Bool{returnrotateCallsCount>0}-var:(rotate)Void)?funcrotate(){rotateCallsCount+=1rotateClosure?()}}上面的文件(AutoMockable.generated.swift)包含了你对mock的期望:使用空方法实现与目标协议的一致性,并检查是否关于调用这些协议方法的变量集的最佳部分......Sourcery为您编写了所有内容!
