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

Reseting Objection's global context storage caches #76

Open
jonah-williams opened this issue Jul 11, 2014 · 2 comments
Open

Reseting Objection's global context storage caches #76

jonah-williams opened this issue Jul 11, 2014 · 2 comments

Comments

@jonah-williams
Copy link
Contributor

Hi folks, I ran across a case where Objection doesn't give me the control I need during testing. I'm curious if anyone else has seen the same issue and if I can propose an appropriate solution in line with the design of the rest of the framework.

I'm writing integration/functional tests where I deliberately exercise many classes, several of which have been instantiated via Objection. Some of these classes are registered with Objection as singletons (via objection_register_singleton()) and as such multiple other classes might have been given references to the same instance.
These singletons introduce our old enemy global mutable state. I want to make sure that state is reset between test cases so that the order in which tests are run cannot influence their outcome (for example a queue of pending network requests might need to be emptied between tests).
As is I might manually reset these states but that requires that my test be aware of, able to access, and coupled to all of these dependencies. I would rather not tightly couple my test of a high level interface to implementation details of classes deep in the object graph the test produces.
Alternately I see [JSObjection reset] which clears the global context. Unfortunately this destroys the JSObjectionInjectorEntrys in that context and the scope with which they were registered as well. Since objection_register_singleton implements +initialize I can't easily re-run those registration calls. As a result classes which were once singletons no longer are.
I considered creating a new JSObjectionInjector instance without the same global context but allowing an injector's global context to not match JSObjection's gObjectionContext seems like a violation of Objection's expected behavior. In addition there's no public mechanism to obtain a JSObjectionInjector's set of modules so I cannot currently init a new injector with the same module set but an empty context.
I can obviously reach into Objection's internals to make this work for now but is there an appropriate public interface we could expose to solve this problem?

What is the intended use of [JSObjection reset]? Is it important that it clear the scope with which classes are registered? Is so does it seem appropriate to introduce a new method which discards the _storageCache from each JSObjectionInjectorEntry in the JSObjection gObjectionContext?

As an example I'd like to be able to write something like:

@interface TestObserver : XCTestObserver
@end

@implementation TestObserver

- (void)testCaseDidStart:(XCTestRun *)testRun {
    [JSObjection resetSingletons];
    [super testCaseDidStart:testRun];
}

@end
@jdewind
Copy link
Contributor

jdewind commented Jul 14, 2014

Jonah,

Singletons are only "global" within the context of an injector. Which means that if you were to create a new injector you would get a new set of singletons.

Unless, of course, you are referring to whether a class is defined as a singleton or not. Then yes, that is globally defined.

@jonah-williams
Copy link
Contributor Author

@dewind you're right, thanks. Working out an implementation I see that I don't need to touch JSObjection's state. It would however be helpful if I could get the set of modules off of the current default injector. That way my test runner does not need to know how to assemble the same set of modules configured in my app and can instead:

- (void)testCaseDidStart:(XCTestRun *)testRun {
    NSArray *modules = [[JSObjection defaultInjector] modules];
    JSObjectionInjector *injector = [JSObjection createInjectorWithModulesArray:modules];
    [JSObjection setDefaultInjector:injector];
    [super testCaseDidStart:testRun];
}

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

2 participants