2009-12-09 9 views
18

OCMock을 사용하여 일부 핵심 데이터 개체를 모의합니다. 이전에, 나는 특성은 오브젝티브 C 1.0 스타일의 명시 적 접근으로 구현했다 :OCMock with Core Data 동적 속성 문제

// -- Old Core Data object header 
@interface MyItem : NSManagedObject {} 
- (NSString *) PDFName; 
- (void) setPDFName:(NSString *)pdfName; 
@end 

// -- implementation provides generated implementations for both getter and setter 

는 지금은 오브젝티브 C 2.0의 코드를 이동하고 새로운 @property 구문을 활용하고자하고, 동적했습니다 코어 데이터 객체에 대한 -generated 메소드 구현 : 나는 모의 항목을 만들 때

// -- New Core Data object header 
@interface MyItem : NSManagedObject {} 
@property (nonatomic, retain) NSString *PDFName; 
@end 

// -- Core Data object implementation 
@implementation MyItem 
@dynamic PDFName; 
@end 

, 지금, 동적 속성을 처리하지 않는 것 :

// -- creating the mock item 
id mockItem = [OCMockObject mockForClass:[MyItem class]]; 
[[[mockItem stub] andReturn:@"fakepath.pdf"] PDFName]; // <-- throws exception here 

T 그는 다음과 같이 오류가 발생합니다 :

Test Case '-[MyItem_Test testMyItem]' started. 
2009-12-09 11:47:39.044 MyApp[82120:903] NSExceptionHandler has recorded the following exception: 
NSInvalidArgumentException -- *** -[NSProxy doesNotRecognizeSelector:PDFName] called! 
Stack trace: 0x916a4d24 0x92115509 0x97879138 0x978790aa 0x9090cb09 0x97820db6 0x97820982 0x10d97ff 0x10d9834 0x9782005d 0x9781ffc8 0x20103d66 0x20103e8c 0x20103642 0x20107024 0x20103642 0x20107024 0x20103642 0x20105bfe 0x907fead9 0x977e4edb 0x977e2864 0x977e2691 0x90877ad9 0xbf565 0xbf154 0x107715 0x1076c3 0x1082e4 0x89d9b 0x8a1e5 0x894eb 0x907e81c7 0x978019a9 0x978013da 0x907dd094 0x907ea471 0x9478c7bd 0x9478c1b9 0x94784535 0x5ede 0x326a 0x5 
Unknown.m:0: error: -[MyItem_Test testMyItem] : *** -[NSProxy doesNotRecognizeSelector:PDFName] called! 

뭐가 잘못 됐나요? 코어 데이터/객체를 @dynamic 속성으로 조롱하는 또 다른 방법이 있습니까?

답변

20

는 또한 OCMock Forum

체크 아웃 http://iamleeg.blogspot.com/2009/09/unit-testing-core-data-driven-apps.html에 교차 게시물에 반응했다.

기본적으로 그는 핵심 데이터 개체의 인터페이스를 프로토콜로 추상화하고 핵심 데이터 개체의 인스턴스를 전달하는 클래스 대신 해당 프로토콜을 사용하는 것이 좋습니다.

핵심 데이터 개체에 대해 이렇게합니다. 그럼 mockForProtocol 사용할 수 있습니다 :

id mockItem = [OCMockObject mockForProtocol:@protocol(MyItemInterface)]; 
[[[mockItem expect] andReturn:@"fakepath.pdf"] PDFName]; 

훌륭한 작품! 그는 또한 단지 특성 합성 인터페이스의 비 핵심 데이터 모의 구현을 만들 것을 제안한다 : 나뿐만 아니라이 사용했습니다

@implementation MockMyItem 
@synthesize PDFName; 
@end 

... 

id <MyItemInterface> myItemStub = [[MockMyItem alloc] init] autorelease]; 
[myItem setPDFName:@"fakepath.pdf"]; 

,하지만 나는 그것이 mockForProtocol 이상 아무것도 추가 확실하지 않다 :/스텁 : 접근하고, 유지하는 것이 한 가지 더 있습니다.

+1

완전성을 위해서 단지 여기에 답을 다시 게시하십시오. 이것은 답이 아닙니다. 그 링크가 죽으면 어떡하지? – Bach

+1

완료 ... OCMock 포럼에서 내 게시물을 복사했습니다. –

+0

테스트에서 실제 NSManagedObject를 사용하지 않는 이유는 무엇입니까? 프로토콜이 관리 대상 객체 모델과 일치하는지 확인하는 다른 테스트가 있습니까? – ImHuntingWabbits

11

위의 대답은 저를위한 프로토콜을 만드는 것을 좋아하지 않으므로 저를 만족시키지 못했습니다. 그래서 더 쉬운 방법이 있다는 것을 알게되었습니다. 대신

[[[mockItem stub] andReturn:@"fakepath.pdf"] PDFName]; // <-- throws exception here 

의 그냥 솔루션의

[[[mockItem stub] andReturn:@"fakepath.pdf"] valueForKey:@"PDFName"]; 
+0

! 훨씬 더 나은 해결책입니다. – Sam

2

하나는 원래 인터페이스의 대체하도록하는 프로토콜을 사용하고 쓸 수 있지만 그것은 조금 무거운 될 수 있으며, 코드의 상당한 양의 리드 당신은 복제해야합니다. 예를 들어, 당신의 단위 테스트 파일 내의, 당신의 단위 테스트 클래스하기 전에,

간단한 범주를 만듭니다 :

개인적으로, 나는 그것이 경량 만들 수있는 방법을 발견 또한

@implementation MyItem(UnitTesing) 
- (NSString *)PDFName{return nil;}; 
@end 

, 당신을 파일을 별도의 파일로 보관할 수 있지만이 파일은 프로덕션 대상의 일부가 아닙니다. 그래서 그것을 같은 테스트 파일에 보관하는 것을 선호합니다.

이 방법의 가장 큰 장점은 관계를 지원하기 위해 XCode로 만든 메서드를 복사하면 안된다는 것입니다. 또한이 카테고리에는 테스트 중에 호출 할 메소드 만 넣을 수 있습니다.

몇 가지주의하지만, 예를 들어, 당신은 세터를 지원하기 위해, 범주 안에 다른 방법을 추가해야합니다있다, 당신은 확인하려고 할 때, 어떻게 올바른 코드가 관리되는 개체의 속성을 변경합니다

- (void)setPDFName:(NSString *)name{}; 
관련 문제