Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to specify override objects #82

Open
drekka opened this issue Jan 21, 2015 · 5 comments
Open

Ability to specify override objects #82

drekka opened this issue Jan 21, 2015 · 5 comments

Comments

@drekka
Copy link

drekka commented Jan 21, 2015

This is to support testing. It would be nice to be able to specify that a particular class registered with Objection is the preferred one to be instantiated. For example, when testing, I could specify a test class (or mock of some sort) will be returned by Objection instead of the one from the app.

The Spring framework has this concept (for Java) and I've found it very useful for providing stubbed out classes for predictable testing scenarios.

Thanks

@drekka
Copy link
Author

drekka commented Jan 21, 2015

I think this could be done via an option argument on the objection_register_singleton macro.

Something like
objection_register_singleton(class, targetClass)
objection_register_singleton(class, targetProtocol)

So whenever an instance of a targetClass or targetProtocol an instance of the class is created. If multiple class register then either an option can be added to the macro to decide which one used or last in best dressed could be used.

@baconpat
Copy link
Member

I've used Objection's modules to accomplish this, (documented here) and it's worked out pretty well. In an integration test where I want to substitute some testing classes I'll create an injector like this:

JSObjectionInjector *injector = [JSObjection createInjector:[TestingObjectionModule new]];

And the TestingObjectionModule would have a configure method something like:

- (void)configure {
    [self bindBlock:^(JSObjectionInjector *context) {
        return [FakeClock new];
    } toClass:[Clock class]];
}

Now, that being said... it would be convenient to be able to change the configuration of an injector after it's been created, but before an instance of a particular class has been requested. Something more lightweight than having to create a new Objection module.

@StatusReport
Copy link

Something more lightweight than having to create a new Objection module.

This is exactly what I did. I wrote a category for JSObjectionInjector which updates a given module (basically just updates the injector context). Then you can create a module with public methods that calls bindBlock:toClass: and bind any object you want (test doubles, for example).

In our code this is pretty transparent to the developer writing tests, since every spec is initializing an injector with this module (and basic modules we configure specifically for testing), and we have macros such as id mockedClass = MockClass([MyObject class]); that create a new mock for class MyObject, set it as the instance that is returned from the injector and returns it back to the user. Then you can perform all your expectations on it and verify them, since this instance is going to be returned from the injector on getObject:.

@drekka
Copy link
Author

drekka commented Jan 22, 2015

Ahh, I was wondering if modules could somehow do this. It wasn't clear to me from reading the documentation. Might be a good idea to add an example showing how this can work in a test situation as I think some people (like myself) will be interested.

Thanks.

@glentregoning
Copy link

@StatusReport yeah +1 to @drekka's suggestion, it would be great if you could add this as an example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants