Skip to content
This repository

Can't insert documents in OCUnit tests #229

Closed
johnnyd opened this Issue · 7 comments

2 participants

johnnyd Jens Alfke
johnnyd

Hi all,
Can't seem to figure this out. It seems that when I'm trying to run some test cases and save a document row for test data I keep getting this error. Btw, I'm not currently interested in doing any replication, just using the embedded "server".

WARNING: CouchRevision initWithOperation failed: Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo=0xed6ebd0 {NSErrorFailingURLKey=touchdb:///mbdb/8F410472-FF77-4A31-B43B-B94B83C3C0A7, NSErrorFailingURLStringKey=touchdb:///mbdb/8F410472-FF77-4A31-B43B-B94B83C3C0A7, NSLocalizedDescription=A server with the specified hostname could not be found.} on RESTOperation[failed GET touchdb:///mbdb/8F410472-FF77-4A31-B43B-B94B83C3C0A7]

Here is the code (Goal is just a subclass of CouchModel):

//The database is alive, thats 100% sure

CouchDatabase *database = viewController.dbManager.database;
CouchDocument *doc = [database untitledDocument];
Goal *goal = [Goal modelForDocument:doc];
goal.goalType = GoalTypeMake;  //Just a string def'd as a constant
goal.goalDescription = @"Write more unit tests!";


RESTOperation *op = [goal save];

if (![op wait]) {
    NSLog(@"Couchdb make goal error is %@",op.error);
}

The interesting thing is that executing this same piece of code when running the app
works perfectly. No errors. Am I missing something here? Thanks in advance for any
assistance!

Jens Alfke
Owner

How are you initializing TouchDB? And how do you know the database is alive?

johnnyd

I have a Singleton that keeps a strong reference to the database, it is initialized as is shown in the wiki:
https://github.com/couchbaselabs/TouchDB-iOS/wiki/Guide%3AAdding-TouchDB-To-Your-App
The only difference is that I don't have a property in the AppDelegate like in the wiki.

Maybe the comment wasn't clear, what I meant to say was that when I run the app (not the application test) then
I can only assume that the database is alive, otherwise I would be alerted of the error (app hard exit) or the test insert would fail. Both of these possibilities do not occur when running the app. When I run the app test however, the database can't be created (thus the error) and therefore I can be reasonably certain that it isn't alive. What I'm trying to figure out is why? I hope it is clearer now. :)

Jens Alfke
Owner

It really looks like TouchDB isn't initialized, from the error you got. Can you show me the code that creates the singleton -- the entire method/function, not just a snippet?

johnnyd

Sure. Here goes....

//Defined in a separate file named GCDSingleton.h and imported into implementation file

#ifndef GCDSingleton_h
#define GCDSingleton_h

#define DEFINE_SHARED_INSTANCE_USING_BLOCK(block) \
static dispatch_once_t pred = 0; \
static id _sharedObject = nil; \
dispatch_once(&pred, ^{ \
_sharedObject = block(); \
}); \
return _sharedObject; \

#endif

/************************
 DBManager.m file 
*************************/

#import "DBManager.h"
#import "GCDSingleton.h"
#import <CouchCocoa/CouchCocoa.h>

@implementation DBManager

+ (DBManager *)db  {

    DEFINE_SHARED_INSTANCE_USING_BLOCK(^{

        return [[self alloc]init];

    });
}

/********************
 database is defined in DBManager.h as:  
 @property (strong,nonatomic,readonly) CouchDatabase *database;
*********************/

- (BOOL)createDatabaseWithName:(NSString *)dbName error:(NSError **)error {

    if (!_database) {

        CouchTouchDBServer *server = [CouchTouchDBServer sharedInstance];
        _database = [server databaseNamed:dbName];

        if (server.error) {
            *error = server.error;
            return NO;
        }

        if (![_database ensureCreated:error]) return NO;
    }

    return YES;
}

I totally agree with you that TouchDB isn't initialized but it seems only when I'm running an application test and not
when I'm running in the simulator. I made a small OCUnit test to show that, for me at least, even if I try to
create a database using exactly the same way as in the wiki, the test fails at the second assertion, in other
words, the database creation step (with the same error as I previously wrote). The test target is an application test that was created when I first created the project so no voodoo there.

#import "CouchDbCreateTests.h"
#import <CouchCocoa/CouchCocoa.h>

@implementation CouchDbCreateTests

- (void)testDatabaseIsCreatedSuccessfully  {

    CouchTouchDBServer *server = [CouchTouchDBServer sharedInstance];
    STAssertNil(server.error, @"server error should be nil!");

    CouchDatabase *database = [server databaseNamed:@"somedb"];
    NSError *error;

    [database ensureCreated:&error];
    STAssertNil(error, @"database error should be nil! Error: \n %@",error);

}


@end

I'm very new to touchDB, so I may be misunderstanding something and thereby doing something(s) very wrong.
I have used the singleton code above in other codebases/projects and they always worked fine so I don't think
this is what the issue is. I may be wrong of course, but then why would the simple test case above be failing?

Jens Alfke
Owner
Jens Alfke
Owner

Thanks for the project. It was a head-scratcher, but the answer turned out to be simple: you linked TouchDB (and CouchCocoa) into your unit test target as well as the main app. Since these are static libraries, it means that you have two copies of the code, one in the app and one in the test bundle, and they're independent of each other (they have different sets of static/global variables, for instance.) The TDServer was getting created with one copy and then accessed with the other, which blew up.

I just deleted TouchDB.framework, TouchDBListener.framework and CouchCocoa.framework from the 'Link Binary With Libraries' list of the MakeOrBreakTests target, did a clean build, and after that the tests succeed.

Jens Alfke snej closed this
johnnyd

Doh!!! Stupid me! Don't know when I did that (must have been late :)) Thanks a million for the help!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.