aboutsummaryrefslogtreecommitdiffhomepage
path: root/Example/Core/Tests/FIRComponentContainerTest.m
diff options
context:
space:
mode:
Diffstat (limited to 'Example/Core/Tests/FIRComponentContainerTest.m')
-rw-r--r--Example/Core/Tests/FIRComponentContainerTest.m157
1 files changed, 157 insertions, 0 deletions
diff --git a/Example/Core/Tests/FIRComponentContainerTest.m b/Example/Core/Tests/FIRComponentContainerTest.m
new file mode 100644
index 0000000..b255973
--- /dev/null
+++ b/Example/Core/Tests/FIRComponentContainerTest.m
@@ -0,0 +1,157 @@
+// Copyright 2018 Google
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#import "FIRTestCase.h"
+
+#import <FirebaseCore/FIRAppInternal.h>
+#import <FirebaseCore/FIRComponent.h>
+#import <FirebaseCore/FIRComponentContainerInternal.h>
+
+#import "FIRTestComponents.h"
+
+/// Internally exposed methods and properties for testing.
+@interface FIRComponentContainer (TestInternal)
+
+@property(nonatomic, strong) NSMutableDictionary<NSString *, FIRComponentCreationBlock> *components;
+@property(nonatomic, strong) NSMutableDictionary<NSString *, id> *cachedInstances;
+
++ (void)registerAsComponentRegistrant:(Class)klass inSet:(NSMutableSet<Class> *)allRegistrants;
+
+- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet<Class> *)allRegistrants;
+
+@end
+
+@interface FIRComponentContainerTest : FIRTestCase
+
+@end
+
+@implementation FIRComponentContainerTest
+
+#pragma mark - Registration Tests
+
+- (void)testRegisteringConformingClass {
+ NSMutableSet<Class> *allRegistrants = [NSMutableSet<Class> set];
+ Class testClass = [FIRTestClass class];
+ [FIRComponentContainer registerAsComponentRegistrant:testClass inSet:allRegistrants];
+ XCTAssertTrue([allRegistrants containsObject:testClass]);
+}
+
+- (void)testRegisteringNonConformingClass {
+ NSMutableSet<Class> *allRegistrants = [NSMutableSet<Class> set];
+ XCTAssertThrows(
+ [FIRComponentContainer registerAsComponentRegistrant:[NSString class] inSet:allRegistrants]);
+ XCTAssertTrue(allRegistrants.count == 0);
+}
+
+- (void)testComponentsPopulatedOnInit {
+ FIRComponentContainer *container = [self containerWithRegistrants:@[ [FIRTestClass class] ]];
+
+ // Verify that the block is stored.
+ NSString *protocolName = NSStringFromProtocol(@protocol(FIRTestProtocol));
+ FIRComponentCreationBlock creationBlock = container.components[protocolName];
+ OCMExpect(creationBlock);
+}
+
+#pragma mark - Caching Tests
+
+- (void)testInstanceCached {
+ FIRComponentContainer *container =
+ [self containerWithRegistrants:@[ [FIRTestClassCached class] ]];
+
+ // Fetch an instance for `FIRTestProtocolCached`, then fetch it again to assert it's cached.
+ id<FIRTestProtocolCached> instance1 = FIR_COMPONENT(FIRTestProtocolCached, container);
+ XCTAssertNotNil(instance1);
+ id<FIRTestProtocolCached> instance2 = FIR_COMPONENT(FIRTestProtocolCached, container);
+ XCTAssertNotNil(instance2);
+ XCTAssertEqual(instance1, instance2);
+}
+
+- (void)testInstanceNotCached {
+ FIRComponentContainer *container = [self containerWithRegistrants:@[ [FIRTestClass class] ]];
+
+ // Retrieve an instance from the container, then fetch it again and ensure it's not the same
+ // instance.
+ id<FIRTestProtocol> instance1 = FIR_COMPONENT(FIRTestProtocol, container);
+ XCTAssertNotNil(instance1);
+ id<FIRTestProtocol> instance2 = FIR_COMPONENT(FIRTestProtocol, container);
+ XCTAssertNotNil(instance2);
+ XCTAssertNotEqual(instance1, instance2);
+}
+
+- (void)testRemoveAllCachedInstances {
+ FIRComponentContainer *container = [self containerWithRegistrants:@[
+ [FIRTestClass class], [FIRTestClassCached class], [FIRTestClassEagerCached class]
+ ]];
+
+ // Retrieve an instance of FIRTestClassCached to ensure it's cached.
+ id<FIRTestProtocolCached> cachedInstance1 = FIR_COMPONENT(FIRTestProtocolCached, container);
+ id<FIRTestProtocolEagerCached> eagerInstance1 =
+ FIR_COMPONENT(FIRTestProtocolEagerCached, container);
+
+ // FIRTestClassEagerCached and FIRTestClassCached instances should be cached at this point.
+ XCTAssertTrue(container.cachedInstances.count == 2);
+
+ // Remove the instances and verify cachedInstances is empty, and that new instances returned from
+ // the container don't match the old ones.
+ [container removeAllCachedInstances];
+ XCTAssertTrue(container.cachedInstances.count == 0);
+
+ id<FIRTestProtocolCached> cachedInstance2 = FIR_COMPONENT(FIRTestProtocolCached, container);
+ XCTAssertNotEqual(cachedInstance1, cachedInstance2);
+ id<FIRTestProtocolEagerCached> eagerInstance2 =
+ FIR_COMPONENT(FIRTestProtocolEagerCached, container);
+ XCTAssertNotEqual(eagerInstance1, eagerInstance2);
+}
+
+#pragma mark - Instantiation Tests
+
+- (void)testEagerInstantiation {
+ // Create a container with `FIRTestClassEagerCached` as a registrant, which provides the
+ // implementation for `FIRTestProtocolEagerCached` and requires eager instantiation as well as
+ // caching so the test can verify it was eagerly instantiated.
+ FIRComponentContainer *container =
+ [self containerWithRegistrants:@[ [FIRTestClassEagerCached class] ]];
+ NSString *protocolName = NSStringFromProtocol(@protocol(FIRTestProtocolEagerCached));
+ XCTAssertNotNil(container.cachedInstances[protocolName]);
+}
+
+#pragma mark - Input Validation Tests
+
+- (void)testProtocolAlreadyRegistered {
+ // Register two classes that provide the same protocol. Only one should be stored, and there
+ // should be a log stating that the protocol has already been registered. Right now there's no
+ // guarantee which one will be registered first since it's an NSSet under the hood, but that could
+ // change in the future.
+ // TODO(wilsonryan): Assert that the log gets called warning that it's already been registered.
+ FIRComponentContainer *container =
+ [self containerWithRegistrants:@[ [FIRTestClass class], [FIRTestClassDuplicate class] ]];
+ XCTAssert(container.components.count == 1);
+}
+
+#pragma mark - Convenience Methods
+
+/// Create a container that has registered the test class.
+- (FIRComponentContainer *)containerWithRegistrants:(NSArray<Class> *)registrants {
+ id appMock = OCMClassMock([FIRApp class]);
+ NSMutableSet<Class> *allRegistrants = [NSMutableSet<Class> set];
+
+ // Initialize the container with the test classes.
+ for (Class c in registrants) {
+ [FIRComponentContainer registerAsComponentRegistrant:c inSet:allRegistrants];
+ }
+
+ return [[FIRComponentContainer alloc] initWithApp:appMock registrants:allRegistrants];
+}
+
+@end