Objective c 对UITextField执行单元测试操作

Objective c 对UITextField执行单元测试操作,objective-c,cocoa-touch,ocunit,ocmock,Objective C,Cocoa Touch,Ocunit,Ocmock,我有一个简单的if条件,当满足该条件时,会添加一个目标,以便在点击“完成”时放下键盘 - (void)addDoneWhenTrue:(UITextField *)input { if (YES) { [input addTarget:self action:@selector(textFieldFinished:) forControlEvents:UIControlEventEditingDidEndOnExit]; } } - (IBAction)

我有一个简单的if条件,当满足该条件时,会添加一个目标,以便在点击“完成”时放下键盘

- (void)addDoneWhenTrue:(UITextField *)input
{
    if (YES)
    {
        [input addTarget:self action:@selector(textFieldFinished:) forControlEvents:UIControlEventEditingDidEndOnExit];
    }
}

- (IBAction)textFieldFinished:(id)sender
{
    [sender resignFirstResponder];
}

我在iOS5上使用OCMock和OCUnit。我如何创建一个单元测试,允许我通过一个简单的
UITextField
输入,并模拟点击它上的“完成”按钮,以验证
辞职FirstResponder
是否发生了?

当然你不需要模拟点击按钮,因为这就是
UIKit
正在处理的事情。您担心调用
textFieldFinished:
方法时会发生正确的事情

免责声明

我很长时间没有使用
OCMock
,因此这是一个仅使用文档的示例,因此它很容易有点不正确-希望有人能够纠正所有设置都是
OCMock
的人

id mock = [OCMockObject mockForClass:[UITextField class]];

[[mock expect] resignFirstResponder];

[sut textFieldFinished:mock]; // sut = system under test - taken from your screen cast ;)

[mock verify];

你不应该嘲笑它,这种目标/行动方法感觉像是一种真正迂回的方式来实现你想要的。只要控制器是
UITextField
的代理,
textfield应返回:
将在点击返回键(或在本例中为完成键)时触发

#pragma mark - UITextFieldDelegate

-(void)textFieldShouldReturn:(UITextField *)textField {
    if (someConditionThatDeterminesWhetherKeyboardShouldCollapse) {
        [textField resignFirstResponder];
    }
}
然后,当您的条件满足或不满足时,您可以在控制器上测试调用
textFieldShouldReturn:
。如果需要,还可以通过调用
loadView
,确保视图已加载到测试用例中,然后断言文本字段的委托是您的控制器,这将确保视图正确连接

-(void)testDoneShouldCollapseKeyboard {
    [controller loadView];
    expect(controller.textField.delegate).to.beIdenticalTo(controller);

    id mockTextField = [OCMockObject partialMockForObject:controller.textField];
    [[mockTextField expect] resignFirstResponder];
    controller.someConditionThatDeterminesWhetherKeyboardShouldCollapse = YES;

    [controller textFieldShouldReturn:controller.textField];

    [mockTextField verify];

    [[mockTextField reject] resignFirstResponder];
    controller.someConditionThatDeterminesWhetherKeyboardShouldCollapse = NO;

    [controller textFieldShouldReturn:controller.textField];

    [mockTextField verify];
}

实际上,我正在寻找一种方法来进行输入。单击,然后使用ocmock断言调用辞职的FirstResponder(使用部分模拟)。我很好奇是否有人能够做到这一点,因为这将产生一个更高级别/更不脆弱的单元测试,而这将是一个集成测试-通常比单元测试更脆弱?我不确定我是否在单元测试
UIKit
组件中看到了价值。仔细看一下您的代码,我想知道您为什么不使用
UITextFieldDelegate
方法
-(void)textfieldDendediting:(UITextField*)textField
?然后,如果您必须进行单元测试,那么您可以确保在某个时候使用正确的委托对象设置textField。在这种情况下,我们当然可以讨论单元/集成是否正确。我能说的是,我正在寻找另一种方式来证明这一点,它与实现无关,而与行为无关。我一遍又一遍地写你提到的那个断言,同样的事情击中了我——如果我在写这个测试时首先考虑到了行为,为什么我不断言它掉了键盘?只是问,因为我一直在寻求改进和这个测试(我写了一遍又一遍)让我觉得我可以做得更好我不确定有没有更好的方法-你正在测试你的代码单元,希望
UITextField
这个黑盒子确实调用了它的委托,然后你也希望
resignFirstResponder
实际上会移除键盘。因此,如果一切都连接正确(您可以测试),那么将调用委托方法
textfielddidediting:
,然后您可以测试它。我想我可以帮助您进行测试,但首先,您为什么要添加此目标/操作?为什么不直接实现
textField应该返回:
with
if(条件)[self.textField resignFirstResponder]有趣-不确定我使用上述实现的真正原因(只是希望基本键盘上的“完成”按钮在单击时将其放下,所以…您有任何可测试的东西,并且这对我有用)您是否有机会进一步澄清这一点?我没有直接在这个控制器上设置委托(只设置输入的目标,但我不确定如何测试)。另外,如果我调用textFieldShouldReturn(但不要实现这个…),我是否遗漏了什么?我目前只有上面显示的textFieldFinishedUpdated示例代码。如果要处理“完成”键,则需要在文本字段上设置委托。代表通常是你的控制者。当你说“完成时点击”,你的意思是键盘右下角的键,对吗?是的-没错(我仍然试图让我的头绕过你上面的精彩帖子)看一看