How can I verify a class method is called using XCTAssert? - swift

I have a service class, I would like to assert 2 things
A method is called
The correct params are passed to that method
Here is my class
protocol OAuthServiceProtocol {
func initAuthCodeFlow() -> Void
func renderOAuthWebView(forService service: IdentityEndpoint, queryitems: [String: String]) -> Void
}
class OAuthService: OAuthServiceProtocol {
fileprivate let apiClient: APIClient
init(apiClient: APIClient) {
self.apiClient = apiClient
}
func initAuthCodeFlow() -> Void {
}
func renderOAuthWebView(forService service: IdentityEndpoint, queryitems: [String: String]) -> Void {
}
}
Here are my tests
class OAuthServiceTests: XCTestCase {
var mockAPIClient: APIClient!
var mockURLSession: MockURLSession!
var sut: OAuthService!
override func setUp() {
mockAPIClient = APIClient()
mockAPIClient.session = MockURLSession(data: nil, urlResponse: nil, error: nil)
sut = OAuthService(apiClient: mockAPIClient)
}
func test_InitAuthCodeFlow_CallsRenderOAuthWebView() {
let renderOAuthWebViewExpectation = expectation(description: "RenderOAuthWebView")
class OAuthServiceMock: OAuthService {
override func initAuthCodeFlow() -> Void {
}
override func renderOAuthWebView(forService service: IdentityEndpoint, queryitems: [String: String]) {
renderOAuthWebViewExpectation.fulfill()
}
}
}
}
I was hoping to create a local sub class of OAuthService, assign that as my sut and call something like like sut.initAuthCodeFlow() and then assert that my expectation was fulfilled.
I believe this should satisfy point 1. However I cannot access my expectation when attempting to assign it as fulfilled as I get the following error
Class declaration cannot close over value
'renderOAuthWebViewExpectation' defined in outer scope
How can I mark this as fulfilled?
I am following a TDD approach, so I understand my OAuthService would produce a failing test at this point anyway*

I was hoping to create a local sub class of OAuthService, assign that as my sut and call something like like sut.initAuthCodeFlow() and then assert that my expectation was fulfilled.
I would strongly discourage you from using this approach. If your SUT is an instance of the subclass then your test is not truly testing OAuthService, but OAuthService mock.
Moreover, if we think of tests as a tool to:
prevent bugs when code is change
help refactoring and maintenance of the code
then I would argue that testing that calling a certain function calls another function is not a good test. That's harsh, I know, so let me unpack why that's the case.
The only thing it's testing is that initAuthCodeFlow() calls renderOAuthWebView(forService:, queryitems:) under the hood. It doesn't have any assertion on the actual behaviour of the system under test, on the outputs it produces directly or not. If I were to edit the implementation of renderOAuthWebView(forService:, queryitems:) and add some code that would crash at runtime this test would not fail.
A test like this doesn't help with keeping the codebase easy to change, because if you want to change the implementation of OAuthService, maybe by adding a parameter to renderOAuthWebView(forService:, queryitems:) or by renaming queryitems into queryItems to match the capitalization, you'll have to update both the production code and the test. In other words, the test will get in your way of refactoring -changing how the code looks without changing how it behaves- without any extra benefit.
So, how should one test OAuthService in a way that prevents bugs and helps moving fast? The trick is all in testing the behaviour instead of the implementation.
What should OAuthService do? initAuthCodeFlow() doesn't return any value, so we can check for direct outputs, but we can still check indirect outputs, side effects.
I'm making a guess here, but I from your test checking that renderOAuthWebView(forService:, queryitems:) I'd and the fact that it gets an APIClient type as input I'd say it'll present some kind of web view for a certain URL, and then make another request to the given APIClient maybe with the OAuth token received from the web view?
A way to test the interaction with APIClient is to make an assertion for the expected endpoint to be called. You can do it with a tool like OHHTTPStubs or with your a custom test double for URLSession that records the requests it gets and allows you to check them.
As for the presentation of the web view, you can use the delegate patter for it, and set a test double conforming to the delegate protocol which records whether it's called or not. Or you could test at a higher level and inspect the UIWindow in which the test are running to see if the root view controller is the one with the web view.
At the end of the day is all a matter of trade offs. The approach you've taken is not wrong, it just optimizes more towards asserting the code implementation rather than its behaviour. I hope that with this answer I showed a different kind of optimization, one biased towards the behaviour. In my experience this style of testing proves more helpful in the medium-long run.

Create a property on your mock, mutating it's value within the method you expect to call. You can then use your XCTAssertEqual to check that prop has been updated.
func test_InitAuthCodeFlow_CallsRenderOAuthWebView() {
let renderOAuthWebViewExpectation = expectation(description: "RenderOAuthWebView")
class OAuthServiceMock: OAuthService {
var renderOAuthWebViewExpectation: XCTestExpectation!
var didCallRenderOAuthWebView = false
override func renderOAuthWebView(forService service: IdentityEndpoint, queryitems: [String: String]) {
didCallRenderOAuthWebView = true
renderOAuthWebViewExpectation.fulfill()
}
}
let sut = OAuthServiceMock(apiClient: mockAPIClient)
XCTAssertEqual(sut.didCallRenderOAuthWebView, false)
sut.renderOAuthWebViewExpectation = renderOAuthWebViewExpectation
sut.initAuthCodeFlow()
waitForExpectations(timeout: 1) { _ in
XCTAssertEqual(sut.didCallRenderOAuthWebView, true)
}
}

Related

Testing a class which preserves its state in private variables

I am writing unit tests for my class. This class preserves its state in some private variables (which I don't want to expose publicly). So the scenario is:
If I call a method, the first time it will keep that state in private properties and call a delegate method with some result.
When I call the same method a second time, the output will be different on the basis of the previous input.
I want to cover all the cases in my tests.
One easy way is to change my private properties to public so that I can mock the previous input in unit test.
The other way is to call the same method with different inputs in the same test twice. Where the first call will keep the state and the next call will be the actual test.
But both these ways seem awkward to me, and I am not sure of the best one.
What is the best way to write unit test for this class?
protocol ZoneUpdateDetectorOutput: class {
func updateZoneState(_ state: ZoneState)
}
class ZoneUpdateDetector {
var zoneChangeTimer: TimerProtocol?
weak var delegate: ZoneUpdateDetectorOutput?
private var previousZoneState: ZoneState?
private var expectedZoneState: ZoneState?
private func updateZoneState() {
// If `expectedZoneState` is not equal to `previousZoneState` then `delegate` will be called
// Otherwise it will just skip
if expectedZoneState != previousZoneState {
delegate?.updateZoneState(expectedZoneState!)
previousZoneState = expectedZoneState
}
}
private func runNotifyZoneStateTimer() {
guard zoneChangeTimer?.isValid() == false else {
return
}
zoneChangeTimer?.start(timeInterval: 5,
onFire: { [weak self] in
guard let strongSelf = self else {
return
}
// On timer fire, it will try to update the state
strongSelf.updateZoneState()
})
}
// When zone changes, this method is invoked
// I basically want to test this method
func zoneStateChanged(_ state: ZoneState) {
expectedZoneState = state
if state != .inZone {
runNotifyZoneStateTimer()
} else {
zoneChangeTimer?.stop()
}
}
}
You should never be testing internal state; you should only test externally (publically) visible behaviour. That way, you can change implementation details of your class without breaking any contracts, and thus without breaking any tests.
So the second option is the preferred one.
After researching and discussing with some experts, I come up with the solution that if we want to test a class which preserve it's state then the functionality which is preserving the state should go under a separate class. Which will serve the same purpose as setting the variables as private. So, ZoneUpdateDetector should have a dependency for example: ZoneUpdateStatePreserver and it should keep the state which was previously inside ZoneUpdateDetector

Class hierarchy - class should only called by another class

I try to implement a Security class and a Secret class. In my whole project the Secret class should only called by Security.getSecretInstance().doSomeSecretAction()
So Secret.doSomeSecretAction() should throw an compile error.
I need the Security.getSecretInstance() for an authentication process.
I'm searching for a good pattern or something else, but I think my searching keywords are too bad or my requirement is stupid/or not possible.
At the moment I call Security.getSecretInstance() it returns a singleton instance of Secret, but I could call Secret.doSomeSecretAction() too. There is no difference.
Do you have some pattern, keywords or snippets for me?
Edit
My definition of awesome would be that I have one method like this:
Security.isAuthorized { secret in
secret.doSomeSecretAction
}, failure {
print("permission denied")
}
And I can get secret only with this .isAuthorized-Method
What I would recommend doing is declare Secret nested inside Security, make Secret private and create non-private methods inside Security that can access Secret. Something like this:
class Security {
class func doSomeSecretAction() {
Secret.doSomeSecretAction()
}
private class Secret {
class func doSomeSecretAction(){
print("Private method called")
}
}
}
Security.doSomeSecretAction()
Here, Security.doSomeSecretAction() can be called from outside the Security class, but Secret.doSomeSecretAction() can only be called inside the Security class.
Update based on comments:
A feasible solution would be declaring the initializer of Security private, so it can only be called from inside the Security class and declaring a computed variable (for now I called it shared) which is the only access point to the initializer. This computed variable either returns nil or a new instance of the Secret class based on Security.isAuthorized. This way, every time a function of Secret is called, the authorisation status is checked and the function can only be called if the status is authorised, otherwise the shared variable returns nil and hence the method is not called.
class Security {
static var isAuthorized = false //change this when the authorisation status changes
class Secret {
static var shared: Secret? {
if Security.isAuthorized {
return Secret()
} else {
return nil
}
}
private init(){} //a new instance of Secret can only be created using the `shared` computed variable, the initializer cannot be called directly from outside the Secret class
func doSomeSecretAction(){
print("Private method called")
}
}
}
Security.Secret.shared //nil
//Security.Secret.init() //if you uncomment this line, you'll get an error saying all initializers are inaccessible
Security.Secret.shared?.doSomeSecretAction() //nil
Security.isAuthorized = true
Security.Secret.shared?.doSomeSecretAction() //function is called
Security.isAuthorized = false
Security.Secret.shared?.doSomeSecretAction() //nil
I was working on this answer while Dávid was editing his; I didn't realize he'd posted an update awhile ago. There's a lot of overlap in our answers, so this is just another style of the same approach.
First, I want to be clear that what you're describing can only implement encapsulation, not "security." I mean that you can build a system that makes it easy for developers to use it correctly and difficult to use it incorrectly. That's pretty straightforward. But you won't be able to stop a developer from extracting the secret and running any code they want. It's their machine and you're giving them the code. They can always run it. They have a debugger; you're not going to hide anything.
But, preventing accidental misuse is a fine goal, and pretty straightforward. The first thing is that you should work with instance methods, not class methods. Class methods makes all of this harder than it needs to be. A solution to your problem will look something like this, relying on fileprivate for most of the access control.
class Security {
enum Error: Swift.Error {
case unauthorized
}
// This feels like it should be nested in Security, but doesn't have to be
class Secret {
// No one outside this file can instantiate one of these. It's likely
// that you'll be passing some parameters here of course.
fileprivate init() {}
// I'm assuming you want these to be single use, so people can't store
// a reference to them an reuse them. This is one simple way.
fileprivate var isAuthorized = true
private func validate() {
// I'm treating this kind of reuse as a programming error and
// crashing. You could throw if you wanted, but it feels like it
// should never happen given your design.
guard isAuthorized else {
fatalError("Secrets can only be used once")
}
}
func doSomeSecretAction() {
// Every "protected" method (which may be all of them) needs to
// call validate() before running.
validate()
print("SECRET!")
}
}
// Public so we can test; obviously this would at least private(set)
var isAuthorized = false
func withAuthorization(execute: (Secret) -> Void) throws {
guard isAuthorized else { throw Error.unauthorized }
// We create a new Secret for every access and invalidate it after.
// That prevents them from being stored and reused.
let secret = Secret()
execute(secret)
secret.isAuthorized = false
}
}
// -- Some other file
let security = Security()
security.isAuthorized = true // For testing
var stealingTheSecret: Security.Secret?
do {
try security.withAuthorization {
$0.doSomeSecretAction() // This is good
stealingTheSecret = $0 // Try to steal it for later use
}
} catch Security.Error.unauthorized {
print("Unauthorized")
}
stealingTheSecret?.doSomeSecretAction() // Let's use it: Crash!
In principle you could get rid of the validate() boilerplate by allocating the memory for Secret directly with UnsafeMutablePointer and destroying it at the end, but this is probably more trouble than it's worth to avoid one extra line of code.
(Note that allocating the memory yourself still wouldn't protect you against the caller saving the object; they can always make a copy of the memory and re-instantiate it with .load; any unsafe thing you can do, so can the caller. This also allows them to circumvent validate() by directly modifying the boolean or copying the object before you invalidate it. There is no technique that will prevent unsafe memory access; this is why you cannot protect secrets inside code.)
After research I find a good and simple solution for me:
class SecurityLayer {
private static var authorized: Bool = false
static func makeAuthorizeCheck() -> API2? {
if authorized {
return API2()
}
return nil
}
}
Second class (not subclass)
class Secret {
func test() {
print("test")
}
fileprivate init() {
}
}
Examples
SecurityLayer.makeAuthorizeCheck()?.test() //working
Secret() //forbidden
Secret.test() //compiler find this method, but there are no permissions to use this one
When the constructor inside Secret is private this wouldn't work anymore. For me the benefit of fileprivate is obvious now.
!The classes have to be in one file!

Swift MVVM testing strategy and code coverage questions

I've run into an issue when generating code coverage with Xcode for view models in an MVVM environment.
Our basic setup is the view controller makes requests to the view model, which in turn calls methods on a data manager that talks to web services.
I came up with what I thought was a reasonably elegant way to test the view models by creating a fake data manager that subclasses the actual data manager and overrides the function called by the VM.
The problem is that for this to work, the VM must be part of the app target and the test target. An apparent side effect of this is that code coverage is not generated for items belonging to two or more targets, even though the unit tests pass. Code coverage is enabled in the project.
Here is a excerpted view model:
import Foundation
class BoosViewModel: BaseViewModel {
convenience override init() {
self.init(dataManager: BoosDataManager(), andModel: nil)
}
func getUnlinkedBoos(_ cardType: CardType) {
(dataManager as! BoosDataManager).getUnlinkedBoos(cardType) { result, error in
...stuff happens here...
}
}
}
... and the data manager
class BoosDataManager: DataManager {
static let SharedInstance: BoosDataManager = {
var manager = BoosDataManager()
return manager
}()
func getUnlinkedBoos(_ cardType: CardType = .loyalty, completion: #escaping ((_ result: BoosModel?, _ error: NSError?) -> Void)) {
...stuff happens here...
}
}
...and the test
class BoosViewModelTests: XCTestCase {
func testGetUnlinkedBoosHappyPath() {
class FauxDataManager: BoosDataManager {
override func getUnlinkedBoos(_ cardType: CardType = .loyalty, completion: #escaping ((_ result: BoosModel?, _ error: NSError?) -> Void)) {
...stuff happens here...
}
}
let viewModel = BoosViewModel()
let dataManager = FauxDataManager()
viewModel.dataManager = dataManager
viewModel.getUnlinkedBoos(.loyalty)
XCTAssertTrue(testObserver.updated)
XCTAssertEqual(testObserver.newViewModel.getBoos().count, 1)
}
}
As I noted earlier the unit tests in this scenario complete successfully, but unit coverage does not get generated.
I have older tests where I actually created an external fake data manager class that was used by the test, the class under test is not part of the test target, and coverage works fine.
The drawback to that is that I have to create multiple data managers to handle specific cases for its returns. If I can't encapsulate the classes, I would need to create a bunch of swift data managers, one for each scenario.
That's why I came up with the internal class.
Now, the problem comes in if I remove the view model under test from the testing target. After doing this, I add #testable import BoosApp to the unit test so that the view model under test can be resolved. When I do this, I get the following error:
Could not cast value of type 'BoosTests.BoosViewModelTests.(testGetUnlinkedBoosHappyPath () -> ()).(FauxDataManager #1)' (0x11f673d18) to 'Boos.BoosDataManager' (0x10444b128).
Aug 30 20:43:01 Pay[19025] : Could not cast value of type 'BoosTests.BoosViewModelTests.(testGetUnlinkedBoosHappyPath () -> ()).(FauxDataManager #1)' (0x11f673d18) to 'Boos.BoosDataManager' (0x10444b128).
I'm not sure what I'm missing. Is there a way to make this scenario work, or am I stuck creating multiple data managers outside of the test code?
Ultimately, I figured out the main issue was that the view model and data manager had somehow gotten added to the test target. After removing them from the test target I was able to make a couple of minor changes and everything is running fine. FYI.

Avoid coupling when using enum in tests

Say we have this enum
enum Action: String {
case doThing
case doOtherThing
}
This enum is used this way:
func run(action: Action, block: () -> Void)
Now, I unit test the run method so I need to pass an Action this way:
func testActionRun() {
let expect = expectation(description: #function)
let sut = ActionRunner()
sut.run(action: .doThing) {
expect.fulfill()
// Assert something
}
waitForExpectations(timeout: 0.1, handler: nil)
}
As I need to test other situations on ActionRunner, I ended with a lot of .doThing spread over the whole test suite.
The problem is: if I make a change in production code and change case doThing to case doThatThing now all my test suite fails because there is no a case doThing.
The perfect thing would be to declare a dummy case in test code to allow something like
sut.run(action: .dummyAction) {
}
but enum does not allow that as it doesn't allows inheritance nor a extension to add a case.
The first option that came to my mind was to convert Action into a protocol, but that change is unnecessary in production and its only purpose is to accomplish something in test code.
So, is it there another option to achieve this?
The question of how to avoid coupling when using enums is a tricky one. I bumped into that myself a few times with no solid answer :/
One point you raise is the one of using a protocol, and that feels unnecessary in production. I sort of agree with that, but most time it's the necessary evil.
In the example you showed though I think maybe a tweak in the design might solve part of the problem.
In particular when looking at this code
func run(action: Action, block: () -> Void) {
// ...
}
func testActionRun() {
let expect = expectation(description: #function)
let sut = ActionRunner()
sut.run(action: .doThing) {
expect.fulfill()
// Assert something
}
waitForExpectations(timeout: 0.1, handler: nil)
}
What comes to mind to me is that your Action specifies a certain behaviour. That is when you test the run method passing .doThing you expect a different behaviour than when passing .doOtherThing.
If that's right, is there any reason why you need to pass the action enum instance and an action block to the run function?
You could separate the code that defines the behaviour from the one performs the actual action even more that what you've done already. For example:
protocol Actionable {
var action: () -> () { get }
}
enum Action: Actionable {
case doThing
case doOtherThing
var action {
switch self {
case .doThing: return ...
case .doOtherThing: return ...
}
}
class ActionRunner {
func run(actionable: Actionable) {
actionable.action()
}
}
func testActionRun() {
let expect = expectation(description: #function)
let sut = ActionRunner()
sut.run(actionable: FakeActionable()) {
expectation.fulfill()
}
waitForExpectations(timeout: 0.1, handler: nil)
}
class FakeActionable: Actionable {
let action = { }
}
func testDoThing() {
let sut = Action.doThing
sut.action()
// XCTAssert for the expected effect of the action
}
Note: I haven't actually compiled that code, so bear with me if it has some mistakes. It should give the idea though.
This way you have ActionRunner which only purpose is to properly run a given Actionable, and the Action enum which only purpose is to describe what different actions should do.
This example code is rather restrict in what it can do, only run () -> () actions, but you could build on top of it to achieve more advanced behaviours.
If you change your production code you have to change your test code too in order to test those new changes.
Maybe you can set the value on an Action variable in the setUp func of your XCTestCase class
import XCTest
class SharingKitTests: XCTestCase {
var theAction: Action!
override func setUp() {
super.setUp()
self.theAction = .doThing
}
}
Then you will be able to use this theAction var in all your test methods, and if you need to change the value you only need to change it in one place.

Swift: Protocol Based Type Construction

I'm trying to create a protocol in Swift I can use for object construction. The problem I'm running into is that I need to store the type information so the type can be constructed later and returned in a callback. I can't seem to find a way to store it without either crashing the compiler or creating build errors. Here's the basics (a contrived, but working example):
protocol Model {
init(values: [String])
func printValues()
}
struct Request<T:Model> {
let returnType:T.Type
let callback:T -> ()
}
We have a simple protocol that declares a init (for construction) and another func printValues() (for testing). We also define a struct we can use to store the type information and a callback to return the new type when its constructed.
Next we create a constructor:
class Constructor {
var callbacks: [Request<Model>] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest<T:Model>(request: Request<T>) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
let model = request.returnType(values: ["value1", "value2"])
request.callback(model)
}
}
}
A couple things to note: This causes a compiler crash. It can't figure this out for some reason. The problem appears to be var callbacks: [Request<Model>] = []. If I comment out everything else, the compiler still crashes. Commenting out the var callbacks and the compiler stops crashing.
Also, the func construct works fine. But it doesn't store the type information so it's not so useful to me. I put in there for demonstration.
I found I could prevent the compiler from crashing if I remove the protocol requirement from the Request struct: struct Request<T>. In this case everything works and compiles but I still need to comment out let model = request.returnType(values: ["value1", "value2"]) in func next(). That is also causing a compiler crash.
Here's a usage example:
func construct() {
let constructor = Constructor()
let request = Request(returnType: TypeA.self) { req in req.printValues() }
//This works fine
constructor.construct(TypeA.self) { a in
a.printValues()
}
//This is what I want
constructor.queueRequest(request)
constructor.next() //The callback in the request object should be called and the values should print
}
Does anyone know how I can store type information restricted to a specific protocol to the type can later be constructed dynamically and returned in a callback?
If you want the exact same behavior of next I would suggest to do this:
class Constructor {
// store closures
var callbacks: [[String] -> ()] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest<T:Model>(request: Request<T>) {
// some code from the next function so you don't need to store the generic type itself
// **EDIT** changed closure to type [String] -> () in order to call it with different values
callbacks.append({ values in
let model = request.returnType(values: values)
request.callback(model)
})
}
func next(values: [String]) {
callbacks.first?(values)
}
}
Now you can call next with your values. Hopefully this works for you.
EDIT: Made some changes to the closure type and the next function
Unfortunately there is no way to save specific generic types in an array and dynamically call their methods because Swift is a static typed language (and Array has to have unambiguous types).
But hopefully we can express something like this in the future like so:
var callbacks: [Request<T: Model>] = []
Where T could be anything but has to conform to Model for example.
Your queueRequest method shouldn't have to know the generic type the Request it's being passed. Since callbacks is an array of Request<Model> types, the method just needs to know that the request being queued is of the type Request<Model>. It doesn't matter what the generic type is.
This code builds for me in a Playground:
class Constructor {
var callbacks: [Request<Model>] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest(request: Request<Model>) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
let model = request.returnType(values: ["value1", "value2"])
request.callback(model)
}
}
}
So I found an answer that seems to do exactly what I want. I haven't confirmed this works yet in live code, but it does compile without any errors. Turns out, I needed to add one more level of redirection:
I create another protocol explicitly for object construction:
protocol ModelConstructor {
func constructWith(values:[String])
}
In my Request struct, I conform to this protocol:
struct Request<T:Model> : ModelConstructor {
let returnType:T.Type
let callback:T -> ()
func constructWith(values:[String]) {
let model = returnType(values: values)
callback(model)
}
}
Notice the actual construction is moved into the Request struct. Technically, the Constructor is no longer constructing, but for now I leave its name alone. I can now store the Request struct as ModelConstructor and correctly queue Requests:
class Constructor {
var callbacks: [ModelConstructor] = []
func queueRequest(request: Request<Model>) {
queueRequest(request)
}
func queueRequest(request: ModelConstructor) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
request.constructWith(["value1", "value2"])
callbacks.removeAtIndex(0)
}
}
}
Note something special here: I can now successfully "queue" (or store in an array) Request<Model>, but I must do so indirectly by calling queueRequest(request: ModelConstructor). In this case, I'm overloading but that's not necessary. What matters here is that if I try to call callbacks.append(request) in the queueRequest(request: Request<Model>) function, the Swift compiler crashes. Apparently we need to hold the compiler's hand here a little so it can understand what exactly we want.
What I've found is that you cannot separate Type information from Type Construction. It needs to be all in the same place (in this case it's the Request struct). But so long as you keep construction coupled with the Type information, you're free to delay/store the construction until you have the information you need to actually construct the object.