如何对EXC_BAD_ACCESS进行单元测试?

gre*_*sus 10 unit-testing objective-c ocunit

我知道如何解决EXC_BAD_ACCESS问题,但我不确定如何对它进行单元测试.有没有办法在代码中捕获EXC_BAD_ACCESS而不是简单地崩溃?

这就是我问的原因:我编写了一个大量使用块的库,如下所示:

- (void)doSomething:(void (^)())myBlock;
Run Code Online (Sandbox Code Playgroud)

在我的实现中,doSomething:我将最终运行块,如下所示:

myBlock();
Run Code Online (Sandbox Code Playgroud)

如果调用者为块传递nil,那么它将崩溃EXC_BAD_ACCESS,因此解决方案是检查该块是否存在,如下所示:

if (myBlock) {
    myBlock();
}
Run Code Online (Sandbox Code Playgroud)

这个零检查很容易忘记,所以我想要一种方法来编写在崩溃发生时失败的单元测试.我认为崩溃可能被视为测试失败,但我认为对于其他试图运行测试以查看错误消息而不是崩溃的人来说会更好.有任何想法吗?

Jos*_*ell 4

我认为您需要在子进程中运行测试;然后你可以让子进程崩溃,检查是否有崩溃,如果发生则让测试失败。

使用Peter Hosey 的单例测试代码

- (void) runTestInSubprocess:(SEL)testCmd {
        pid_t pid = fork();
        // The return value of fork is 0 in the child process, and it is
        // the id of the child process in the parent process.
        if (pid == 0) {
            // Child process: run test
            // isInSubprocess is an ivar of your test case class
            isInSubprocess = YES;
            [self performSelector:testCmd];
            exit(0);
        } else {
            // Parent process: wait for child process to end, check 
            // its status
            int status;
            waitpid(pid, &status, /*options*/ 0);
            // This was a crash; fail the test
            STAssertFalse(WIFSIGNALED(status), @"Test %@ crashed due to signal %d", NSStringFromSelector(testCmd), WTERMSIG(status));
        }
}
Run Code Online (Sandbox Code Playgroud)

然后,每个测试将在子进程中自行运行,如下所示:

- (void) testSomething {
    if (!isInSubprocess) {
            // Hand off this test's selector to be run in a subprocess
            [self runTestInSubprocess:_cmd];
            return;
    }

    // Put actual test code here
    STAssertEquals(1, 1, @"Something wrong with the universe.");

}
Run Code Online (Sandbox Code Playgroud)

你可能需要调整这个;我还没有测试过。