台风加载情节提要以编程方式似乎可以执行异步实例化而不会阻塞

金塔纳

我正在开发一个iOS应用程序,并试图将Typhoon集成到测试中。我目前正在尝试模拟来自情节提要的视图控制器中的依赖项,因此在我的程序集中使用:

public dynamic var systemComponents: SystemComponents!
public dynamic func storyboard() -> AnyObject {
    return TyphoonDefinition.withClass(TyphoonStoryboard.self) {
        (definition) in
        definition.useInitializer("storyboardWithName:factory:bundle:") {
            (initializer) in
            initializer.injectParameterWith("Main")
            initializer.injectParameterWith(self)
            initializer.injectParameterWith(NSBundle.mainBundle())
        }
    }
}

我想创建一个CameraModeViewController(我正在进行单元测试的类),它依赖于模拟出的提供系统相机功能的协议。依赖项是dynamic var cameraProvider: CameraAPIProvider?我认为我正确地创建了一个替换协作装配来替换systemComponentsMockSystemComponentsSystemComponents重写功能的子类这是我注入模拟的地方:

let assembly = ApplicationAssembly().activateWithCollaboratingAssemblies([
                            MockSystemComponents(camera: true)
                        ])
let storyboard = assembly.storyboard()
subject = storyboard.instantiateViewControllerWithIdentifier("Camera-Mode") as! CameraModeViewController

测试中的下一行代码是let _ = subject.view,据我viewDidLoad所知,这是调用并获取所有与情节提要链接的IBOutlet的技巧,此测试需要其中之一。

但是,我得到的结果非常神秘:有时但并非总是如此,所有测试都会失败,因为在viewDidLoad调用依赖项(cameraProvider)后,我收到了“无法识别的消息发送给类”错误。该错误似乎表明在发送消息时(这是协议中的正确实例方法CameraAPIProvider),该字段当前是CLASS而不是实例:它+[MockSystemCamera cameraStreamLayer]按错误消息中的报告解释消息。

~~~但是~~~

这里的踢球者:如果我在两个电话之间添加一个断点assembly.storyboard()subject.view,测试总是通过。一切都已正确设置,并且消息已正确发送到实例,而无需使用这种“类方法”伪造的解释。因此,我想知道Typhoon是否在我必须等待的注入过程中执行某种异步过程?可能仅在处理情节提要提供的视图控制器时?如果是这样,是否有任何方法可以确保其阻止?

深入研究Typhoon的源代码一段时间后,我得到的印象是,该TyphoonDefinition(Instance Builder) initializeInstanceWithArgs:factory:方法中有一个__block id instance临时为Class类型的对象,然后被该类型的实例替换;并且可能可以不阻塞地异步调用它,因此注入的成员保留为Class类型?


更新:添加的代码MockSystemComponents(camera:)请注意,SystemComponents继承自TyphoonAssembly

@objc
public class MockSystemComponents: SystemComponents {
    var cameraAvailable: NSNumber

    init(camera: NSNumber) {
        self.cameraAvailable = camera
        super.init()
    }

    public override func systemCameraProvider() -> AnyObject {
        return TyphoonDefinition.withClass(MockSystemCamera.self) {
            (definition) in
            definition.useInitializer("initWithAvailable:") {
                (initializer) in
                initializer.injectParameterWith(self.cameraAvailable)
            }
        }
    }
}

更新#2:我尝试用MockSystemComponents.systemCameraProvider()属性注入替换中的构造函数注入。不同的问题,但是我怀疑原因是相同的:现在,注入的属性(声明为可选)仍然nil是我解开包装的一部分时间(但并非总是如此-大概有4/5的测试运行失败,大约和以前一样)。


更新#3:尝试使用以下代码块,根据此答案使用工厂构造(请注意,直接设置工厂不能像OP那样起作用,但我认为我正确使用了响应Jasper问题而添加的功能)。结果与使用属性注入(如上面的Update#2)相同,因此没有骰子。

金塔纳

实际上,甚至在调用实例化之前就已经出现了这个问题。事实上,这个问题是组件不通常意欲状态。有几种方法可以解决此问题,但是不建议使用我使用的一种方法-具有成员变量和初始化方法。这样做的问题在于,在activateWithCollaboratingAssemblies方法中,将枚举程序集的所有实例方法以进行定义,并且实际上将在协作程序集上调用初始化程序。因此,即使您使用初始化程序创建程序集,也可能会使用虚假值再次调用该程序集。

请注意,出现异步行为的原因实际上是定义的汇编存在不确定性的顺序(将其存储在NSDictionary中的属性)。这意味着,如果activateWithCollaboratingAssemblies碰巧先枚举依赖状态的方法,它们会很好地工作;但是,如果首先枚举了初始化程序,并且销毁了状态,则创建之后的定义将被取消。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

台风加载情节提要以编程方式似乎可以执行异步实例化而不会阻塞

来自分类Dev

如何从情节提要以编程方式加载UIViewController?

来自分类Dev

视图不会在ViewController上以不同的情节提要以编程方式呈现

来自分类Dev

Swift-以编程方式加载情节提要

来自分类Dev

如何在没有情节提要的情况下以编程方式实例化视图控制器

来自分类Dev

台风情节提要集成

来自分类Dev

重新加载情节提要以更改区域设置

来自分类Dev

重新加载情节提要以更改区域设置

来自分类Dev

以编程方式获取情节提要ID

来自分类Dev

添加视图。情节提要VS。以编程方式

来自分类Dev

以编程方式获取情节提要ID

来自分类Dev

以编程方式从viewController导航到情节提要

来自分类Dev

在没有情节提要的情况下以编程方式加载UITableViewController

来自分类Dev

是否可以在情节提要中旋转图像,还是必须以编程方式进行处理?

来自分类Dev

UICollectionView宽度以编程方式与情节提要板初始化冲突

来自分类Dev

在OS X情节提要中通过标识符实例化拆分视图控制器不会加载视图层次结构

来自分类Dev

UIViewController扩展可从情节提要实例化

来自分类Dev

在WPF ControlTemplate中以编程方式创建情节提要

来自分类Dev

以编程方式创建UIButton比使用情节提要模糊

来自分类Dev

如何以编程方式或在情节提要中将UIImageView居中

来自分类Dev

以编程方式在TFS工作项中创建情节提要链接

来自分类Dev

如何以编程方式创建翻译情节提要动画UWP?

来自分类Dev

快速更改高度以编程方式锚定(无情节提要)

来自分类Dev

以编程方式创建UIButton比使用情节提要模糊

来自分类Dev

以编程方式在TFS工作项中创建情节提要链接

来自分类Dev

以编程方式从情节提要中显示当前视图

来自分类Dev

如何以编程方式或在情节提要中将UIImageView居中

来自分类Dev

以编程方式更改情节提要上的UIView的大小

来自分类Dev

完全以编程方式创建情节提要C#

Related 相关文章

  1. 1

    台风加载情节提要以编程方式似乎可以执行异步实例化而不会阻塞

  2. 2

    如何从情节提要以编程方式加载UIViewController?

  3. 3

    视图不会在ViewController上以不同的情节提要以编程方式呈现

  4. 4

    Swift-以编程方式加载情节提要

  5. 5

    如何在没有情节提要的情况下以编程方式实例化视图控制器

  6. 6

    台风情节提要集成

  7. 7

    重新加载情节提要以更改区域设置

  8. 8

    重新加载情节提要以更改区域设置

  9. 9

    以编程方式获取情节提要ID

  10. 10

    添加视图。情节提要VS。以编程方式

  11. 11

    以编程方式获取情节提要ID

  12. 12

    以编程方式从viewController导航到情节提要

  13. 13

    在没有情节提要的情况下以编程方式加载UITableViewController

  14. 14

    是否可以在情节提要中旋转图像,还是必须以编程方式进行处理?

  15. 15

    UICollectionView宽度以编程方式与情节提要板初始化冲突

  16. 16

    在OS X情节提要中通过标识符实例化拆分视图控制器不会加载视图层次结构

  17. 17

    UIViewController扩展可从情节提要实例化

  18. 18

    在WPF ControlTemplate中以编程方式创建情节提要

  19. 19

    以编程方式创建UIButton比使用情节提要模糊

  20. 20

    如何以编程方式或在情节提要中将UIImageView居中

  21. 21

    以编程方式在TFS工作项中创建情节提要链接

  22. 22

    如何以编程方式创建翻译情节提要动画UWP?

  23. 23

    快速更改高度以编程方式锚定(无情节提要)

  24. 24

    以编程方式创建UIButton比使用情节提要模糊

  25. 25

    以编程方式在TFS工作项中创建情节提要链接

  26. 26

    以编程方式从情节提要中显示当前视图

  27. 27

    如何以编程方式或在情节提要中将UIImageView居中

  28. 28

    以编程方式更改情节提要上的UIView的大小

  29. 29

    完全以编程方式创建情节提要C#

热门标签

归档