In this case you'd only be calling the setter during unit testing. Something like this: public class QuestionsController : ControllerBase { private IQuestionsRepository _repository = new SqlQuestionsRepository(); // Really only called during unit testing... public QuestionsController(IQuestionsRepository repository) { _repository = repository; } } I'm not too familiar with . NET but as a side note in Java this is a common way to refactor existing code to improve the testability.
I.E. , if you have classes that are already in use and need to modify them so as to improve code coverage without breaking existing functionality Our team has done this before, and usually we set the visibility of the setter to package-private and keep the package of the test class the same so that it can call the setter.
In this case you'd only be calling the setter during unit testing. Something like this: public class QuestionsController : ControllerBase { private IQuestionsRepository _repository = new SqlQuestionsRepository(); // Really only called during unit testing... public QuestionsController(IQuestionsRepository repository) { _repository = repository; } } I'm not too familiar with . NET but as a side note in Java this is a common way to refactor existing code to improve the testability.
I.E. , if you have classes that are already in use and need to modify them so as to improve code coverage without breaking existing functionality. Our team has done this before, and usually we set the visibility of the setter to package-private and keep the package of the test class the same so that it can call the setter.
Peter, very good suggestion. Have you had any experience with using IoC containers on your projects or have you not found a need yet? – Simucal Jun 25 '09 at 2:43 I don't have much .
NET experience, most of my work is with Java using Spring for IoC. It has been very useful for improving modularity. – Peter Jun 25 '09 at 2:45 @Peter: This is pretty much the pattern that I use.
I posted an answer that does the same thing, but uses some C# language features that you, being a Java guy, might not be aware of. – Seth Petry-Johnson Jan 8 '10 at 15:19.
You could have a default constructor with your controller that will have some sort of default behavior. Something like... public QuestionsController() : this(new QuestionsRepository()) { } That way by default when the controller factory is creating a new instance of the controller it will use the default constructor's behavior. Then in your unit tests you could use a mocking framework to pass in a mock into the other constructor.
One options is to use fakes. Public class FakeQuestionsRepository : IQuestionsRepository { public FakeQuestionsRepository() { } //simple constructor //implement the interface, without going to the database } TestFixture public class QuestionsControllerTest { Test public void should_be_able_to_instantiate_the_controller() { //setup the scenario var repository = new FakeQuestionsRepository(); var controller = new QuestionsController(repository); //assert some things on the controller } } Another options is to use mocks and a mocking framework, which can auto-generate these mocks on the fly. TestFixture public class QuestionsControllerTest { Test public void should_be_able_to_instantiate_the_controller() { //setup the scenario var repositoryMock = new Moq.Mock(); repositoryMock .
SetupGet(o => o. FirstQuestion) . Returns(new Question { X = 10 }); //repositoryMock.
Object is of type IQuestionsRepository: var controller = new QuestionsController(repositoryMock. Object); //assert some things on the controller } } Regarding where all the objects get constructed. In a unit test, you only set up a minimal set of objects: a real object which is under test, and some faked or mocked dependencies which the real object under test requires.
For example, the real object under test is an instance of QuestionsController - it has a dependency on IQuestionsRepository, so we give it either a fake IQuestionsRepository like in the first example or a mock IQuestionsRepository like in the second example. In the real system, however, you set up the whole of the container at the very top level of the software. In a Web application, for example, you set up the container, wiring up all of the interfaces and the implementing classes, in GlobalApplication.
Application_Start.
I'm expanding on Peter's answer a bit. In applications with a lot of entity types, it is not uncommon for a controller to require references to multiple repositories, services, whatever. I find it tedious to manually pass all those dependencies in my test code (especially since a given test may only involve one or two of them).
In those scenarios, I prefer setter-injection style IOC over constructor injection. The pattern I use it this: public class QuestionsController : ControllerBase { private IQuestionsRepository Repository { get { return _repo? (_repo = IoC.GetInstance()); } set { _repo = value; } } private IQuestionsRepository _repo; // Don't need anything fancy in the ctor public QuestionsController() { } } Replace IoC.
GetInstance with whatever syntax your particular IOC framework uses. In production use nothing will invoke the property setter, so the first time the getter is called the controller will call out to your IOC framework, get an instance, and store it. In test, you just need to call the setter prior to invoking any controller methods: var controller = new QuestionsController { Repository = MakeANewMockHoweverYouNormallyDo(...); } The benefits of this approach, IMHO: Still takes advantage of IOC in production.
Easier to manually construct your controllers during testing. You only need to initialize the dependencies your test will actually use. Possible to create test-specific IOC configurations, if you don't want to manually configure common dependencies.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.