Dependency Injection and Unit test this constructor
I have a constructor and a property in the class:
private IMyCollectionObjects _myCollectionObjects;
public MyClassConstructor(string message)
{
_myCollectionObjects = MyCollect开发者_JS百科ion.GetCollectionObejects(message);
}
With as much detail can you please help me understand how to unit test this constructor and GetCollectionObjects method?
How do I completely decouple the classes? You can give the answer using any IoC, I want to understand the concept.
Thank you.
Dependencies on static members such as GetCollectionObjects
are difficult to test because you can't replace its implementation at runtime. This means that you cannot fully isolate an instance of MyClassConstructor
from the implementation details of GetCollectionObjects
. Without isolation of the test target, it can't really be considered a unit test.
See here for further discussion of static dependencies.
You can refactor this code to be fully decoupled (and thus fully testable):
private readonly IMyCollectionObjects _myCollectionObjects;
public MyClassConstructor(IMyCollectionObjects myCollectionObjects)
{
_myCollectionObjects = myCollectionObjects;
}
This bubbles the knowledge of how to turn a message into a collection right out of MyClassConstructor
, making the class simpler, more cohesive, and less coupled.
For of all, unit testing is all about unitary testing, that is, one thing at a time.
With as much detail can you please help me understand how to unit test this constructor and
GetCollectionObjects
method?
First things first, have you unit tested your MyCollection
class?
If not, you should begin with it, as your MyClassConstructor
class depends on it, that is the basis of dependency injection. Otherwise, how can you manage to know if the results you're getting are right or wrong? You won't be able to test and be sure that it works flawlessly.
How do I completely decouple the classes? You can give the answer using any IoC, I want to understand the concept.
I my humble point of view, you must have a clear reason to make an object dependant of another using dependency injection. Once you make an object depend on another, it makes no sense, in my opinion, to decouple them. One way of decoupling might be to use Unity Application Block of Enterprise Library.
Unit test this constructor
You generally only need to check for three things while testing such a constructor.
- That the constructor doesn't return a null value;
- That the instance it returns is of the expected type;
- That the object you expect to be instantiated through its dependency is actually instiated.
[TestCase("message")] public void DependentConstructorTest(string message) { MyClassConstructor myclass = new MyClassConstructor(message); Assert.IsNotNull(myclass); Assert.IsInstanceOf(typeof(MyClassConstructor), myclass); Assert.IsNotNull(myclass.MyCollection); // Where MyCollection represents the property that // exposes the instance created of the object from // which your MyClassConstructor class depends on. }
Note: This test is written using NUnit attributes and assertion methods. Use whatever else you like.
Here is roughly what you would need to do (with some assumptions).
Assuming MyCollection is a static class and GetCollectionObjects parses a string and returns an IMyCollectionObjects, you would first need to make MyCollection non-static, and pass it through the constructor as well. Static classes/methods used in a class create a tight coupling, more or less by definition.
Now you would be constructing the class passing a message string and a MyCollection. Your constructor uses the two in combination to populate a member variable of type IMyCollectionObjects. In order to ensure that this happens as expected, you will need a way to examine the result from outside the class (i.e. a public method). So you will need a property getter that exposes _myCollectionObjects.
Now you just need to call this contructor from one or more tests, and check the property after construction to ensure parsing the string into a collection was successful.
Note that this is really more of an integration test than a discrete unit test. You are really testing that the parsing was successful. If the class represented here is really what you intend to test, the test would really just be checking that GetCollectionObjects was called. The result of that call is really irrelevant, because you would (presumably) have a separate test or set of tests that ensure that the method GetCollectionObjects on MyCollection works as expected.
精彩评论