erikdoe / ocmock

Mock objects for Objective-C
http://ocmock.org
Apache License 2.0
2.16k stars 606 forks source link

OCMock Are you trying to mock the init method? This is currently not supported #407

Closed HiMelody closed 4 years ago

HiMelody commented 4 years ago
@implementation UserService

- (NSArray *)getUserInfos {
        UserDao *dao = [[UserDao alloc] init];
    NSArray *result = [dao get];
    return result;
}

@end

- (void)testGetUserInfos {
    id daoMock = OCMClassMock([UserDao class]);
    OCMStub([daoMock alloc]).andReturn(daoMock);
    OCMStub([daoMock init]).andReturn(daoMock);

    UserService *service = [UserService new];
    [service getUserInfos];

    OCMVerify([daoMock get]);
}

failed: caught "NSInternalInconsistencyException", "** Method init invoked twice on stub recorder. Are you trying to mock the init method? This is currently not supported."

How to mock [[UserDao alloc] init];

dmaclach commented 4 years ago

From the docs it says:

IMPORTANT: It is not possible to stub the init method, because that is implemented by the mock itself. However, when the init method is called again a after the original initialisation the mock object simply returns self. This makes it possible to effectively stub an alloc/init sequence.

If you remove the OCMStub([daoMock init]).andReturn(daoMock); does it work for you?

dmaclach commented 4 years ago

PR #410 Fixes up the case where the exception wasn't being passed through the macro.

HiMelody commented 4 years ago

From the docs it says:

IMPORTANT: It is not possible to stub the init method, because that is implemented by the mock itself. However, when the init method is called again a after the original initialisation the mock object simply returns self. This makes it possible to effectively stub an alloc/init sequence.

If you remove the OCMStub([daoMock init]).andReturn(daoMock); does it work for you?

I remove OCMStub([daoMock init]).andReturn(daoMock); , it work for me. But i stub [dao get], it doesn't work, [dao get] return nil;

- (void)testGetUserInfos {
    id daoMock = OCMClassMock([UserDao class]);
    OCMStub([daoMock alloc]).andReturn(daoMock);

    NSArray *resultArray = @[@"test"];
    OCMStub([daoMock get]).andReturn(resultArray);

    UserService *service = [UserService new];
    [service getUserInfos];

    OCMVerify([daoMock get]);
}
dmaclach commented 4 years ago

Using current top of tree OCMock:

@interface UserDao : NSObject
@end

@implementation UserDao
- (NSArray *)get {
  return @[@"Happy"];
}
@end

@interface UserService : NSObject
@end

@implementation UserService

- (NSArray *)getUserInfos {
        UserDao *dao = [[UserDao alloc] init];
  NSArray *result = [dao get];
  return result;
}

@end

@interface DaoTest : XCTestCase
@end

@implementation DaoTest
- (void)testGetUserInfos {
    id daoMock = OCMClassMock([UserDao class]);
    OCMStub([daoMock alloc]).andReturn(daoMock);
    NSArray *resultArray = @[@"test"];
    OCMStub([daoMock get]).andReturn(resultArray);

    UserService *service = [UserService new];
    NSArray *result = [service getUserInfos];
    XCTAssertEqualObjects(resultArray, result);
    OCMVerify([daoMock get]);

}
@end

works fine for me and passes tests.

HiMelody commented 4 years ago

Using current top of tree OCMock:

@interface UserDao : NSObject
@end

@implementation UserDao
- (NSArray *)get {
  return @[@"Happy"];
}
@end

@interface UserService : NSObject
@end

@implementation UserService

- (NSArray *)getUserInfos {
        UserDao *dao = [[UserDao alloc] init];
  NSArray *result = [dao get];
  return result;
}

@end

@interface DaoTest : XCTestCase
@end

@implementation DaoTest
- (void)testGetUserInfos {
    id daoMock = OCMClassMock([UserDao class]);
    OCMStub([daoMock alloc]).andReturn(daoMock);
    NSArray *resultArray = @[@"test"];
    OCMStub([daoMock get]).andReturn(resultArray);

    UserService *service = [UserService new];
    NSArray *result = [service getUserInfos];
    XCTAssertEqualObjects(resultArray, result);
    OCMVerify([daoMock get]);

}
@end

works fine for me and passes tests.

My project OCMock version is 3.3.1, it doesn't work. I update to 3.6 ,it works. thanks