I am working on a legacy code base and I need to find a way to write unit tests for this project.
The project has a three layer architecture (UI-Biz-DAL
as we call them) and DAL
is totally implemented using ADO.Net
and Typed-Datasets
and it is full of SQL Scripts
.
Our Biz
classes have methods that are responsible for doing business logic stuffs and they are dependent on other helper classes and DAL
classes.
I know I can use DI
to inject these classes to my Biz
classes but I think that I should change a lot of code. Here's a solution that I can think of :
There's this TestContext
class that acts as a container and can contain mock objects for tests but it does not have anything when it comes to run the actual code so that real objects can be used instead , here is an example :
var dal=TestContext.Current.Resolve<IMyDAL>(@default:new MyDal());
as you can see Resolve method accepts an argument of type IMyDAL
that will be used in case of not running our tests.
First I would like to know what do you think about this solution
Second I am still thinking about a way to test SQL scripts that are hardcoded in our code base . How can I test them ?
2 Answers 2
What you're suggesting is homebrewed DI tightly coupled to each business object and auto-wiring the current behavior.
Just. no. Use a real DI solution, and auto-wire THAT to the legacy DAL.
Change the code. You're writing tests here, man, that's the Lord's work.
-
I agree with you to some extent but It involves a lot of change in our code and I am afraid that it can make people anxious :)Beatles1692– Beatles16922016年01月03日 07:19:42 +00:00Commented Jan 3, 2016 at 7:19
-
If you do your job right you'll be preventing anxiety for years to come. I think what you're proposing is an equivalent level of code change, and what's more because it is tightly coupled it fails to achieve the goal of DI -- which is the binding of code objects to independent interfaces rather than tightly coupling concretions to each other.Matthew Mark Miller– Matthew Mark Miller2016年01月03日 07:30:47 +00:00Commented Jan 3, 2016 at 7:30
-
I couldn't agree more. Actually I am suggesting this
TestContext
object as a temporary solution so we can have our code refactored without having to add aIoC container
in the first place.When everything is in place we can removeTestContext
and replace it with a realIoC container
.Beatles1692– Beatles16922016年01月03日 07:39:17 +00:00Commented Jan 3, 2016 at 7:39 -
Instead of using an
IoC container
can we use a defaultctor
that calls the injectionctor
with concrete objects ?Beatles1692– Beatles16922016年01月03日 08:03:57 +00:00Commented Jan 3, 2016 at 8:03 -
Ugh, I dunno man, anything you do the concretions short of introducing IoC is going to increase the total amount of effort. Have you thought about simply introducing assembly or package local mutators for the services you want to inject, something that would obviously only be for testing?Matthew Mark Miller– Matthew Mark Miller2016年01月03日 08:19:21 +00:00Commented Jan 3, 2016 at 8:19
Depending on your version of studio you can use Microsoft Fakes, in particular shims to be able to mock most things - https://msdn.microsoft.com/en-us/library/hh549176.aspx .
Once your library is covered with tests you can have these as a safety net while you introduce proper DI and fully isolated tests.
The danger is that shims are evil and can let developers get away with bad practice.
Explore related questions
See similar questions with these tags.
TypeMock
.