单元测试从启动视图控制器错误地执行代码

Posted

技术标签:

【中文标题】单元测试从启动视图控制器错误地执行代码【英文标题】:Unit test is incorrectly executing code from the launch view controller 【发布时间】:2015-12-11 20:11:51 【问题描述】:

我有一个简单的结构如下,它是 ios 应用程序的一部分:

struct Country: JSONObject 
    let name: String!
    let code: String!

    static let nameKey = "name"
    static let codeKey = "dial_code"

    init?(_ json: [String: AnyObject]) throws 
        guard let name = json[Country.nameKey] as? String else 
           throw JSONError.InvalidTypeForKey(key: Country.nameKey)
        

        guard let code = json[Country.codeKey] as? String else 
            throw JSONError.InvalidTypeForKey(key: Country.codeKey)
        

        self.name = name
        self.code = code
    

我写了一个单元测试来测试这个类的初始化:

func testCorrectInitialisationOfCountry() 
    let countryDict = [Country.nameKey: "England", Country.codeKey: "+44"]

    do 
        let country = try Country(countryDict)!
        XCTAssert(countryDict[Country.nameKey] == country.name, "The country name does not match")
        XCTAssert(countryDict[Country.codeKey] == country.code, "The country code does not match")
    
    catch _ 
        print("Initialisation of country failed with an exception")
    

我面临的问题是这个结构在我的应用的第一个视图控制器的 viewDidLoad() 方法中被初始化了几次。

由于某种原因,当我运行测试并因此生成不正确的代码覆盖率时,会调用 viewDidLoad() 方法。下图是 Xcode 生成的单元测试统计数据。

数字“241”实际上应该只是“1”。其他 240 次,该行正在从未测试的启动视图控制器执行。

如何阻止视图控制器代码执行?

提前致谢。

【问题讨论】:

【参考方案1】:

单元测试在您正在运行的应用的上下文中运行。

我认为最好的办法是编写应用程序委托的 didFinishLaunchingWithOptions,以便在通过测试启动时不调出视图控制器(或调出更简单的)

此答案提供了一种检查您的应用是否在单元测试中运行的方法:

https://***.com/a/30306450/3937

要停止第一个故事板的自动加载,请将其作为启动故事板删除,并按照以下答案自行编写加载代码:

https://***.com/a/16702730/3937

【讨论】:

感谢您的回答!但是我正在使用情节提要,并且我的启动情节提要设置在我的 xcodeproj 文件中。如果您使用情节提要,我不知道有什么方法可以阻止 VC 在 AppDelegate 中加载。如果可以的话,请您分享一个代码sn-p吗? 谢谢!!在代码中启动情节提要的第二个代码 sn-p 不太有效,但只需要在它之前添加以下行: self.window = UIWindow(frame: UIScreen.mainScreen().bounds)【参考方案2】:

您应该使用setUp 方法(在您的单元测试类中),该方法在viewDidLoad 之后调用。

重写此方法以自定义测试用例中所有测试的初始状态。

这样,您可以在测试方法执行之前重置您需要的任何内容。

例如,我需要重置通过视图控制器调用的单例。请注意,您可以通过tearDown 方法在各个方法之间进行重置:

在每个测试完成后调用一次。覆盖此方法以执行任何每次测试的清理。

【讨论】:

【参考方案3】:

您的问题有一个解决方案。您可以按照以下链接中的说明缩短您的应用启动。

How To: Unit Test Without Running The Entire App

【讨论】:

以上是关于单元测试从启动视图控制器错误地执行代码的主要内容,如果未能解决你的问题,请参考以下文章

单元测试

Spring boot web 单元测试程序

Django单元测试测试视图问题,怎么解决

Grails 单元测试问题

软件测试流程

如何快速调试 sCrypt 单元测试错误