QA@IT
«回答へ戻る

指摘を受けてコードを修正。

5599
+すいません、stripさんの指摘の通りコードが間違ってました。
+テスト失敗になっていたのは `(IBAction)showEraseSheet:(id)sender` でActionSheetを作成していたためです。
+最初showEraseSheetがただのメソッドだとおもっていたんですが、途中でIBActionだと気付いて意図せずオーバーロードになってしまっていました(ただの言い訳です)。
+aActionSheetはプロパティで設定するので showEraseSheetのAction時には設定する必要はありませんでした。 
+
+ここを修正するとテストはパスします。
+shunsuke_h2006 さんのコードでもaActionSheetがメソッド呼び出しによって変更されていないか確認してみてください。
+
+---
+
 pod setupの待ち時間の長さに挫折しそうになりましたが試しにやってみました。
-再現しました。一応ちゃんと動くコードもできましたが原因は追えていません。
-再現コードに関して説明がなかった部分は想像で書いています。
+説明がなかった部分は想像で書いています。
+最初コードが間違っていたため再現したように見えましたが、修正によりテストは通過するようになりました。
 
 Single View Applicationにボタンを置き、以下のようなコードで発生します。
 
 ```objc
 // @endの前あたりに以下の2メソッド追加
 
-- (void)showEraseSheet{
-    // [[self aActionSheet]
-    //        showInView: [[[[UIApplication sharedApplication]
-    //                        keyWindow] subviews] lastObject]];
-    
-    [[self aActionSheet] showInView:self.view];
-}
+// 追記の際に修正: 以下は不要になりました。
+// - (void)showEraseSheet{
+// }
 
 - (IBAction)showEraseSheet:(id)sender {
-    _aActionSheet = [[UIActionSheet alloc]
-                     initWithTitle:@"title"
-                     delegate:nil
-                     cancelButtonTitle:nil
-                     destructiveButtonTitle:nil
-                     otherButtonTitles:@"button1", nil];
-    [self showEraseSheet];
-    _aActionSheet = nil;
+    // 追記の際に修正: showInViewのみになりました。
+
+    [[self aActionSheet] showInView:self.view];
 }
 ```
 
 }
 ```
 
-テストコードのvc.viewをnilにすれば `unexpected method invoked` になるのでメソッド呼び出しのテストはできていると思います。
-書いた私が言うのもなんですが、何故こちらだとうまくいくかはわかりません。プロパティが原因なのかもしれないと思っていますが、そこぐらいしか違いが見出せないからですし。
-メソッドでUIActionSheetを生成したのも単に私の好みなのでたまたまです。
-こんな回答で申し訳ないですが、参考までにどうぞ。
+参考までにどうぞ。

すいません、stripさんの指摘の通りコードが間違ってました。
テスト失敗になっていたのは (IBAction)showEraseSheet:(id)sender でActionSheetを作成していたためです。
最初showEraseSheetがただのメソッドだとおもっていたんですが、途中でIBActionだと気付いて意図せずオーバーロードになってしまっていました(ただの言い訳です)。
aActionSheetはプロパティで設定するので showEraseSheetのAction時には設定する必要はありませんでした。

ここを修正するとテストはパスします。
shunsuke_h2006 さんのコードでもaActionSheetがメソッド呼び出しによって変更されていないか確認してみてください。


pod setupの待ち時間の長さに挫折しそうになりましたが試しにやってみました。
説明がなかった部分は想像で書いています。
最初コードが間違っていたため再現したように見えましたが、修正によりテストは通過するようになりました。

Single View Applicationにボタンを置き、以下のようなコードで発生します。

ViewController.h

@interface ViewController : UIViewController

@property UIActionSheet *aActionSheet;
@property (weak, nonatomic) IBOutlet UIButton *showerasebutton;
- (IBAction)showEraseSheet:(id)sender;

@end

ViewController.m

// @endの前あたりに以下の2メソッド追加

// 追記の際に修正: 以下は不要になりました。
// - (void)showEraseSheet{
// }

- (IBAction)showEraseSheet:(id)sender {
    // 追記の際に修正: showInViewのみになりました。

    [[self aActionSheet] showInView:self.view];
}

テストコード
~~Test.m

- (void)testElaseSheet
{
    id mockactionsheet = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockeraser = [OCMockObject mockForClass:[UIButton class]];

    ViewController *vc = [[ViewController alloc]init];
    vc.aActionSheet = mockactionsheet;


    [[mockactionsheet expect] showInView:vc.view];

    [vc showEraseSheet:mockeraser];

    [mockactionsheet verify];
}

で、これを書く前に試しで書いてみたコードだとうまくいきました。
上記コードに以下の様に追記します。

ViewController.h

@interface ViewController : UIViewController
〜中略〜

// 以下の3行を追加
@property (weak, nonatomic) IBOutlet UIButton *button;
- (IBAction)buttonClick:(id)sender;
- (UIActionSheet*) generateActionSheet;

@end

ViewController.m

// @implementation を変更
@implementation ViewController{
    UIActionSheet *actionSheet;
}

〜中略〜

// 以下3メソッドを@endの前に追加

- (UIActionSheet*) generateActionSheet{
    return [[UIActionSheet alloc]
            initWithTitle:@"title"
            delegate:nil
            cancelButtonTitle:nil
            destructiveButtonTitle:nil
            otherButtonTitles:@"button1", nil];
}

- (void)showSheet{
    actionSheet = [self generateActionSheet];
    [actionSheet showInView:self.view];
    actionSheet = nil;
}

- (IBAction)buttonClick:(id)sender {
    [self showSheet];
}

テストコード
~~Test.m

- (void)testActionSheet
{
    id mockAC = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockButton = [OCMockObject mockForClass:[UIButton class]];

    ViewController *vc = [[ViewController alloc]init];
    vc.button = mockButton;
    id mockVC = [OCMockObject partialMockForObject:vc];
    [[[mockVC stub] andReturn:mockAC] generateActionSheet];


    [[mockAC expect] showInView:vc.view];

    [vc buttonClick:mockButton];

    [mockAC verify];
}

参考までにどうぞ。

すいません、stripさんの指摘の通りコードが間違ってました。
テスト失敗になっていたのは `(IBAction)showEraseSheet:(id)sender` でActionSheetを作成していたためです。
最初showEraseSheetがただのメソッドだとおもっていたんですが、途中でIBActionだと気付いて意図せずオーバーロードになってしまっていました(ただの言い訳です)。
aActionSheetはプロパティで設定するので showEraseSheetのAction時には設定する必要はありませんでした。 

ここを修正するとテストはパスします。
shunsuke_h2006 さんのコードでもaActionSheetがメソッド呼び出しによって変更されていないか確認してみてください。

---

pod setupの待ち時間の長さに挫折しそうになりましたが試しにやってみました。
説明がなかった部分は想像で書いています。
最初コードが間違っていたため再現したように見えましたが、修正によりテストは通過するようになりました。

Single View Applicationにボタンを置き、以下のようなコードで発生します。

ViewController.h
```objc
@interface ViewController : UIViewController

@property UIActionSheet *aActionSheet;
@property (weak, nonatomic) IBOutlet UIButton *showerasebutton;
- (IBAction)showEraseSheet:(id)sender;

@end
```

ViewController.m
```objc
// @endの前あたりに以下の2メソッド追加

// 追記の際に修正: 以下は不要になりました。
// - (void)showEraseSheet{
// }

- (IBAction)showEraseSheet:(id)sender {
    // 追記の際に修正: showInViewのみになりました。

    [[self aActionSheet] showInView:self.view];
}
```

テストコード
~~Test.m
```objc
- (void)testElaseSheet
{
    id mockactionsheet = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockeraser = [OCMockObject mockForClass:[UIButton class]];
    
    ViewController *vc = [[ViewController alloc]init];
    vc.aActionSheet = mockactionsheet;
    
    
    [[mockactionsheet expect] showInView:vc.view];
    
    [vc showEraseSheet:mockeraser];
    
    [mockactionsheet verify];
}
```

---

で、これを書く前に試しで書いてみたコードだとうまくいきました。
上記コードに以下の様に追記します。

ViewController.h
```objc
@interface ViewController : UIViewController
〜中略〜

// 以下の3行を追加
@property (weak, nonatomic) IBOutlet UIButton *button;
- (IBAction)buttonClick:(id)sender;
- (UIActionSheet*) generateActionSheet;

@end
```

ViewController.m
```objc
// @implementation を変更
@implementation ViewController{
    UIActionSheet *actionSheet;
}

〜中略〜

// 以下3メソッドを@endの前に追加

- (UIActionSheet*) generateActionSheet{
    return [[UIActionSheet alloc]
            initWithTitle:@"title"
            delegate:nil
            cancelButtonTitle:nil
            destructiveButtonTitle:nil
            otherButtonTitles:@"button1", nil];
}

- (void)showSheet{
    actionSheet = [self generateActionSheet];
    [actionSheet showInView:self.view];
    actionSheet = nil;
}

- (IBAction)buttonClick:(id)sender {
    [self showSheet];
}
```

テストコード
~~Test.m
```objc
- (void)testActionSheet
{
    id mockAC = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockButton = [OCMockObject mockForClass:[UIButton class]];
    
    ViewController *vc = [[ViewController alloc]init];
    vc.button = mockButton;
    id mockVC = [OCMockObject partialMockForObject:vc];
    [[[mockVC stub] andReturn:mockAC] generateActionSheet];

    
    [[mockAC expect] showInView:vc.view];

    [vc buttonClick:mockButton];
    
    [mockAC verify];
}
```

参考までにどうぞ。

5599
 }
 ```
 
-テストモジュール
+テストコード
+~~Test.m
 ```objc
 - (void)testElaseSheet
 {
 ```
 
 テストコード
+~~Test.m
 ```objc
 - (void)testActionSheet
 {

pod setupの待ち時間の長さに挫折しそうになりましたが試しにやってみました。
再現しました。一応ちゃんと動くコードもできましたが原因は追えていません。
再現コードに関して説明がなかった部分は想像で書いています。

Single View Applicationにボタンを置き、以下のようなコードで発生します。

ViewController.h

@interface ViewController : UIViewController

@property UIActionSheet *aActionSheet;
@property (weak, nonatomic) IBOutlet UIButton *showerasebutton;
- (IBAction)showEraseSheet:(id)sender;

@end

ViewController.m

// @endの前あたりに以下の2メソッド追加

- (void)showEraseSheet{
    // [[self aActionSheet]
    //        showInView: [[[[UIApplication sharedApplication]
    //                        keyWindow] subviews] lastObject]];

    [[self aActionSheet] showInView:self.view];
}

- (IBAction)showEraseSheet:(id)sender {
    _aActionSheet = [[UIActionSheet alloc]
                     initWithTitle:@"title"
                     delegate:nil
                     cancelButtonTitle:nil
                     destructiveButtonTitle:nil
                     otherButtonTitles:@"button1", nil];
    [self showEraseSheet];
    _aActionSheet = nil;
}

テストコード
~~Test.m

- (void)testElaseSheet
{
    id mockactionsheet = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockeraser = [OCMockObject mockForClass:[UIButton class]];

    ViewController *vc = [[ViewController alloc]init];
    vc.aActionSheet = mockactionsheet;


    [[mockactionsheet expect] showInView:vc.view];

    [vc showEraseSheet:mockeraser];

    [mockactionsheet verify];
}

で、これを書く前に試しで書いてみたコードだとうまくいきました。
上記コードに以下の様に追記します。

ViewController.h

@interface ViewController : UIViewController
〜中略〜

// 以下の3行を追加
@property (weak, nonatomic) IBOutlet UIButton *button;
- (IBAction)buttonClick:(id)sender;
- (UIActionSheet*) generateActionSheet;

@end

ViewController.m

// @implementation を変更
@implementation ViewController{
    UIActionSheet *actionSheet;
}

〜中略〜

// 以下3メソッドを@endの前に追加

- (UIActionSheet*) generateActionSheet{
    return [[UIActionSheet alloc]
            initWithTitle:@"title"
            delegate:nil
            cancelButtonTitle:nil
            destructiveButtonTitle:nil
            otherButtonTitles:@"button1", nil];
}

- (void)showSheet{
    actionSheet = [self generateActionSheet];
    [actionSheet showInView:self.view];
    actionSheet = nil;
}

- (IBAction)buttonClick:(id)sender {
    [self showSheet];
}

テストコード
~~Test.m

- (void)testActionSheet
{
    id mockAC = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockButton = [OCMockObject mockForClass:[UIButton class]];

    ViewController *vc = [[ViewController alloc]init];
    vc.button = mockButton;
    id mockVC = [OCMockObject partialMockForObject:vc];
    [[[mockVC stub] andReturn:mockAC] generateActionSheet];


    [[mockAC expect] showInView:vc.view];

    [vc buttonClick:mockButton];

    [mockAC verify];
}

テストコードのvc.viewをnilにすれば unexpected method invoked になるのでメソッド呼び出しのテストはできていると思います。
書いた私が言うのもなんですが、何故こちらだとうまくいくかはわかりません。プロパティが原因なのかもしれないと思っていますが、そこぐらいしか違いが見出せないからですし。
メソッドでUIActionSheetを生成したのも単に私の好みなのでたまたまです。
こんな回答で申し訳ないですが、参考までにどうぞ。

pod setupの待ち時間の長さに挫折しそうになりましたが試しにやってみました。
再現しました。一応ちゃんと動くコードもできましたが原因は追えていません。
再現コードに関して説明がなかった部分は想像で書いています。

Single View Applicationにボタンを置き、以下のようなコードで発生します。

ViewController.h
```objc
@interface ViewController : UIViewController

@property UIActionSheet *aActionSheet;
@property (weak, nonatomic) IBOutlet UIButton *showerasebutton;
- (IBAction)showEraseSheet:(id)sender;

@end
```

ViewController.m
```objc
// @endの前あたりに以下の2メソッド追加

- (void)showEraseSheet{
    // [[self aActionSheet]
    //        showInView: [[[[UIApplication sharedApplication]
    //                        keyWindow] subviews] lastObject]];
    
    [[self aActionSheet] showInView:self.view];
}

- (IBAction)showEraseSheet:(id)sender {
    _aActionSheet = [[UIActionSheet alloc]
                     initWithTitle:@"title"
                     delegate:nil
                     cancelButtonTitle:nil
                     destructiveButtonTitle:nil
                     otherButtonTitles:@"button1", nil];
    [self showEraseSheet];
    _aActionSheet = nil;
}
```

テストコード
~~Test.m
```objc
- (void)testElaseSheet
{
    id mockactionsheet = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockeraser = [OCMockObject mockForClass:[UIButton class]];
    
    ViewController *vc = [[ViewController alloc]init];
    vc.aActionSheet = mockactionsheet;
    
    
    [[mockactionsheet expect] showInView:vc.view];
    
    [vc showEraseSheet:mockeraser];
    
    [mockactionsheet verify];
}
```

---

で、これを書く前に試しで書いてみたコードだとうまくいきました。
上記コードに以下の様に追記します。

ViewController.h
```objc
@interface ViewController : UIViewController
〜中略〜

// 以下の3行を追加
@property (weak, nonatomic) IBOutlet UIButton *button;
- (IBAction)buttonClick:(id)sender;
- (UIActionSheet*) generateActionSheet;

@end
```

ViewController.m
```objc
// @implementation を変更
@implementation ViewController{
    UIActionSheet *actionSheet;
}

〜中略〜

// 以下3メソッドを@endの前に追加

- (UIActionSheet*) generateActionSheet{
    return [[UIActionSheet alloc]
            initWithTitle:@"title"
            delegate:nil
            cancelButtonTitle:nil
            destructiveButtonTitle:nil
            otherButtonTitles:@"button1", nil];
}

- (void)showSheet{
    actionSheet = [self generateActionSheet];
    [actionSheet showInView:self.view];
    actionSheet = nil;
}

- (IBAction)buttonClick:(id)sender {
    [self showSheet];
}
```

テストコード
~~Test.m
```objc
- (void)testActionSheet
{
    id mockAC = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockButton = [OCMockObject mockForClass:[UIButton class]];
    
    ViewController *vc = [[ViewController alloc]init];
    vc.button = mockButton;
    id mockVC = [OCMockObject partialMockForObject:vc];
    [[[mockVC stub] andReturn:mockAC] generateActionSheet];

    
    [[mockAC expect] showInView:vc.view];

    [vc buttonClick:mockButton];
    
    [mockAC verify];
}
```

テストコードのvc.viewをnilにすれば `unexpected method invoked` になるのでメソッド呼び出しのテストはできていると思います。
書いた私が言うのもなんですが、何故こちらだとうまくいくかはわかりません。プロパティが原因なのかもしれないと思っていますが、そこぐらいしか違いが見出せないからですし。
メソッドでUIActionSheetを生成したのも単に私の好みなのでたまたまです。
こんな回答で申し訳ないですが、参考までにどうぞ。

回答を投稿

pod setupの待ち時間の長さに挫折しそうになりましたが試しにやってみました。
再現しました。一応ちゃんと動くコードもできましたが原因は追えていません。
再現コードに関して説明がなかった部分は想像で書いています。

Single View Applicationにボタンを置き、以下のようなコードで発生します。

ViewController.h

@interface ViewController : UIViewController

@property UIActionSheet *aActionSheet;
@property (weak, nonatomic) IBOutlet UIButton *showerasebutton;
- (IBAction)showEraseSheet:(id)sender;

@end

ViewController.m

// @endの前あたりに以下の2メソッド追加

- (void)showEraseSheet{
    // [[self aActionSheet]
    //        showInView: [[[[UIApplication sharedApplication]
    //                        keyWindow] subviews] lastObject]];

    [[self aActionSheet] showInView:self.view];
}

- (IBAction)showEraseSheet:(id)sender {
    _aActionSheet = [[UIActionSheet alloc]
                     initWithTitle:@"title"
                     delegate:nil
                     cancelButtonTitle:nil
                     destructiveButtonTitle:nil
                     otherButtonTitles:@"button1", nil];
    [self showEraseSheet];
    _aActionSheet = nil;
}

テストモジュール

- (void)testElaseSheet
{
    id mockactionsheet = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockeraser = [OCMockObject mockForClass:[UIButton class]];

    ViewController *vc = [[ViewController alloc]init];
    vc.aActionSheet = mockactionsheet;


    [[mockactionsheet expect] showInView:vc.view];

    [vc showEraseSheet:mockeraser];

    [mockactionsheet verify];
}

で、これを書く前に試しで書いてみたコードだとうまくいきました。
上記コードに以下の様に追記します。

ViewController.h

@interface ViewController : UIViewController
〜中略〜

// 以下の3行を追加
@property (weak, nonatomic) IBOutlet UIButton *button;
- (IBAction)buttonClick:(id)sender;
- (UIActionSheet*) generateActionSheet;

@end

ViewController.m

// @implementation を変更
@implementation ViewController{
    UIActionSheet *actionSheet;
}

〜中略〜

// 以下3メソッドを@endの前に追加

- (UIActionSheet*) generateActionSheet{
    return [[UIActionSheet alloc]
            initWithTitle:@"title"
            delegate:nil
            cancelButtonTitle:nil
            destructiveButtonTitle:nil
            otherButtonTitles:@"button1", nil];
}

- (void)showSheet{
    actionSheet = [self generateActionSheet];
    [actionSheet showInView:self.view];
    actionSheet = nil;
}

- (IBAction)buttonClick:(id)sender {
    [self showSheet];
}

テストコード

- (void)testActionSheet
{
    id mockAC = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockButton = [OCMockObject mockForClass:[UIButton class]];

    ViewController *vc = [[ViewController alloc]init];
    vc.button = mockButton;
    id mockVC = [OCMockObject partialMockForObject:vc];
    [[[mockVC stub] andReturn:mockAC] generateActionSheet];


    [[mockAC expect] showInView:vc.view];

    [vc buttonClick:mockButton];

    [mockAC verify];
}

テストコードのvc.viewをnilにすれば unexpected method invoked になるのでメソッド呼び出しのテストはできていると思います。
書いた私が言うのもなんですが、何故こちらだとうまくいくかはわかりません。プロパティが原因なのかもしれないと思っていますが、そこぐらいしか違いが見出せないからですし。
メソッドでUIActionSheetを生成したのも単に私の好みなのでたまたまです。
こんな回答で申し訳ないですが、参考までにどうぞ。

pod setupの待ち時間の長さに挫折しそうになりましたが試しにやってみました。
再現しました。一応ちゃんと動くコードもできましたが原因は追えていません。
再現コードに関して説明がなかった部分は想像で書いています。

Single View Applicationにボタンを置き、以下のようなコードで発生します。

ViewController.h
```objc
@interface ViewController : UIViewController

@property UIActionSheet *aActionSheet;
@property (weak, nonatomic) IBOutlet UIButton *showerasebutton;
- (IBAction)showEraseSheet:(id)sender;

@end
```

ViewController.m
```objc
// @endの前あたりに以下の2メソッド追加

- (void)showEraseSheet{
    // [[self aActionSheet]
    //        showInView: [[[[UIApplication sharedApplication]
    //                        keyWindow] subviews] lastObject]];
    
    [[self aActionSheet] showInView:self.view];
}

- (IBAction)showEraseSheet:(id)sender {
    _aActionSheet = [[UIActionSheet alloc]
                     initWithTitle:@"title"
                     delegate:nil
                     cancelButtonTitle:nil
                     destructiveButtonTitle:nil
                     otherButtonTitles:@"button1", nil];
    [self showEraseSheet];
    _aActionSheet = nil;
}
```

テストモジュール
```objc
- (void)testElaseSheet
{
    id mockactionsheet = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockeraser = [OCMockObject mockForClass:[UIButton class]];
    
    ViewController *vc = [[ViewController alloc]init];
    vc.aActionSheet = mockactionsheet;
    
    
    [[mockactionsheet expect] showInView:vc.view];
    
    [vc showEraseSheet:mockeraser];
    
    [mockactionsheet verify];
}
```

---

で、これを書く前に試しで書いてみたコードだとうまくいきました。
上記コードに以下の様に追記します。

ViewController.h
```objc
@interface ViewController : UIViewController
〜中略〜

// 以下の3行を追加
@property (weak, nonatomic) IBOutlet UIButton *button;
- (IBAction)buttonClick:(id)sender;
- (UIActionSheet*) generateActionSheet;

@end
```

ViewController.m
```objc
// @implementation を変更
@implementation ViewController{
    UIActionSheet *actionSheet;
}

〜中略〜

// 以下3メソッドを@endの前に追加

- (UIActionSheet*) generateActionSheet{
    return [[UIActionSheet alloc]
            initWithTitle:@"title"
            delegate:nil
            cancelButtonTitle:nil
            destructiveButtonTitle:nil
            otherButtonTitles:@"button1", nil];
}

- (void)showSheet{
    actionSheet = [self generateActionSheet];
    [actionSheet showInView:self.view];
    actionSheet = nil;
}

- (IBAction)buttonClick:(id)sender {
    [self showSheet];
}
```

テストコード
```objc
- (void)testActionSheet
{
    id mockAC = [OCMockObject mockForClass:[UIActionSheet class]];
    id mockButton = [OCMockObject mockForClass:[UIButton class]];
    
    ViewController *vc = [[ViewController alloc]init];
    vc.button = mockButton;
    id mockVC = [OCMockObject partialMockForObject:vc];
    [[[mockVC stub] andReturn:mockAC] generateActionSheet];

    
    [[mockAC expect] showInView:vc.view];

    [vc buttonClick:mockButton];
    
    [mockAC verify];
}
```

テストコードのvc.viewをnilにすれば `unexpected method invoked` になるのでメソッド呼び出しのテストはできていると思います。
書いた私が言うのもなんですが、何故こちらだとうまくいくかはわかりません。プロパティが原因なのかもしれないと思っていますが、そこぐらいしか違いが見出せないからですし。
メソッドでUIActionSheetを生成したのも単に私の好みなのでたまたまです。
こんな回答で申し訳ないですが、参考までにどうぞ。