You can still replace components, both using the pattern I showed in that GitHub ticket and using normal components, but the resolution order has changed. i.e. whereas in version 0.3 you would pass stubs after the component
app = App(components=[AComponent(), AComponentStub()])
in 0.4+ you have to pass stubs first
app = App(components=[AComponentStub(), AComponent()])
That said, yeah, testability is the reason I came up with
SingletonComponent in our app. Being able to stub out a component at test setup time is really valuable and a lot clearer than trying to mock stuff out.
SingletonComponent doesn’t solve the problem for components that ought to be singletons but that depend on other components (i.e. singletons that have to be instantiated lazily). I did come up with a
LazySingletonComponent at one point but it turned out pretty ugly so I threw it away.