我知道如何解决EXC_BAD_ACCESS问题,但我不确定如何对其进行单元测试。有没有办法在代码中捕获EXC_BAD_ACCESS而不是简单地崩溃?
这就是我要问的原因:我写了一个大量使用块的库,如下所示:
- (void)doSomething:(void (^)())myBlock;
在我doSomething:
的实施中,我将最终运行该块,如下所示:
myBlock();
如果调用者为块传递nil,那么它将与EXC_BAD_ACCESS
一起崩溃,因此解决方案是检查该块是否存在,如下所示:
if (myBlock) {
myBlock();
}
这个零检查很容易忘记,因此我想要一种编写崩溃发生时失败的单元测试的方法。我认为崩溃可能被视为测试失败,但我认为对于其他试图运行测试以查看错误消息而不是崩溃的人来说会更好。有什么想法吗?
答案 0 :(得分:4)
我认为你需要在子进程中运行测试;然后你可以让子进程崩溃,检查崩溃,如果它发生的话,整齐地测试失败。
从Peter Hosey's singleton test code开始工作。
- (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));
}
}
然后,每个测试都会在子进程中运行,如下所示:
- (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.");
}
你可能需要调整一下;我还没有测试过。
答案 1 :(得分:1)
我建议使用Assertions and Logging Programming Guide
中的一个断言宏所以你可以这样做:
NSAssert(myBlock != nil, @"myBlock must not be nil")
这会强制执行方法继续执行之前必须满足的前提条件。它还允许应用程序崩溃,并为您提供除EXEC_BAD_ACCESS以外的原因。