An application can pass every test, run flawlessly in development and crash on its first call in Production because a service it needs is
null. No compiler and no unit test sees that, because the error isn’t in a method but in the wiring, and in development the wiring is
different from Production. In this lesson you reproduce the error in a small practice application, write the test that finds it, and give the
Kladde a startup test that will report something like this in the pull request from now on.
Field report: a registration quietly returns null
In one project a library was updated. It registered a type anew with a key and, without the documentation making a point of it, the same type
additionally without a key, with a factory that returned null. The application asked for the type without a key. The container said nothing,
because from its point of view a factory may return whatever it likes. The tests ran in development, with a different configuration, and
were green. In Production a service received null in its constructor, and for a week every request failed at a place where nobody had
expected null.
The cause was a library, but you can easily make the same kind of mistake yourself. Three typical forms:
- A factory returns
null.AddSingleton(sp => …Get<T>()!):Get<T>()returnsnullwhen the section is missing from the configuration, and the!silences the compiler. - A service isn’t registered at all. It appears only in a branch
if (builder.Environment.IsDevelopment())or was forgotten during a refactoring. - A singleton holds on to a scoped service (lesson 2.3.3). The service is created once and tied to the first
DbContextforever.