The problem that we're encountering in the testing of the single record Finder is to do with the fact
that we have a dependency upon essentially the details of how a database provides its data because we're
depending directly on the singleton database and the fact that it's a singleton.
So why don't we use a little bit of dependency injection now depends on injection doesn't imply that
you have to have some special heavyweight library to perform the injection.
It just means that you have a point at which you can insert the dependency instead of the actual object
and what we want to do here is we want to have a dummy database instead of the real database.
So in order to do this we're going to give the singleton database an interface we're going to define
a base class which is going to have just one virtual member for actually getting the population.
So it's this member that get population member that we're actually interested in faking and getting
a different set of results a set of predictable results so here what I'm going to do is I'll make a
class called database and this is going to define the interface for any kind of database that we work
with.
So it's just going to have one public member which is going to be virtual In get population which takes
a common string name and is going to be pure virtual.
So as you can see Singleton database already implements this interface so we can just say public database
and we are done because this interface is already available and you can see it here down below.
OK so this is good.
And what this lets us do is it lets us now make a kind of fake database a database where the members
are predictable.
So lets do that.
OK so down here we are going to have a class called dummy database dummy database is going to also implement
database and we are going to actually implemented the members.
So lets go into implement functions and we only need population which should be public.
Thats the only thing that we need to do now in terms of the data storage.
We want to have some dummy data here so I'm going to have a map from string to end capitals once again
but this time around in the constructor what I'm going to do is I'm going to basically fake it I'm going
to initialize it with some dummy data.
So we go into constructor I'm just going to choose select none in here because I'm going to initialize
these capitals with a bunch of data.
So we're going to have capitals at now for being equal to 1.
And I'll replicate this and we'll have beta in gamma.
So as you can see this set of data is not going to change as the database changes because it's fixed.
And as a result we can test the record finder using this data because whenever somebody calls get population
all we have to do is where it's own capitals population for this name and that's all that we have to
do really.
Now what we need to do is we need a different kind of Singleton record finder we need a record finder
where instead of having direct access to the singleton this part the part that I've highlighted here
is actually a dependency and this is the whole point of dependency injection.
So we're going to have a configurable record finder struct configurable record finder.
There we go.
OK so the idea is that we keep the database that we we're working with as a dependency.
So here is a reference to the database itself.
Notice I'm referencing database not Singleton database or dummy database.
You can substitute one for another at any point in time.
And having made this what I can do is I can initialize it in the constructor like so so.
Fairly simple stuff.
And then I can get out of the total population so I need a function which looks just like this.
So I'm actually going to copy it over and paste it in here.
But instead of taking this hard dependency on the database all I have to do is just cold be here because
that's what's going to be provided in the constructor.
And that's pretty much it.
That's all that we need to do and now we can write better tests.
Now we can write an actual unit test as opposed to just an integration test.
So let's do exactly that.
So I'm going to have another test in my records finder tests and this one is going to be called dependent.
Total population test.
OK.
So this time around I'll make a dummy database
like so and then I will make a configurable record finder Aref which gets injected the database in this
case I'm simply providing it as the constructor argument.
And then I can write my expected this time round.
I know what kind of values I have because I know I have alpha beta and gamma with simulated populations
of just one two and three.
So for example if I add the Alpha and the gamma I expect four.
And so I will get four if I call R.F. don't get the total population with a vector.
So we're going to have off a string and this vector is going to have alpha alpha and gamma like so OK
so this is as you can see a much neater test because we don't have to go into the actual database and
we don't have to look up what the actual values are and we're not in any way dependent on campus those
thoughts t XTi and not changing as we kind of expand our test base.
So once again I'm going to run this set of tests that we have and hopefully the second test passes as
well.
All right.
And as you can see the test passes just fine.
So this is a much better way of dealing with a dependency on the singleton.
So the issue here isn't so much that the singleton is an bad idea it's that the singleton is a bad idea
if you have a hard dependence on it like you have if you just use its access or if you use the getter
but if you have your test in terms of a in a dependency that you can substitute for something that's
more testable then everything is fine.
So what we did in order to accommodate this is we extracted an interface called database and then we
implemented this interface in a dummy database which has some predictable data.
And as a consequence what we ended up with effectively here is we ended up with a unit test whereas
here we have an integration test.