Fendy
Fendy

Reputation: 4643

What to be Tested in Layered Dependency Injection

The relative question maybe like this one question.

I used a dependency injection as architecture of my application. Then I have created unit testing for it.

The injection architecture may be like this:

IClassA(IClassB)
IClassB(IClassC1, IClassC2)
//more of it

Please take a note that this architecture only involve service objects, not repositories. Now I am wondering, what class to be tested.

Any suggestion or thoughts will be appreciated.

EDIT:

A working scenario is for when I want to give a file info (for csv or xml based), then convert to an entity. The process will be:

An example code for Classes will be like this (I skip the constructor injection part):

public class ClassA: IClassA{
  public IEnumerable<Request> GetRequestFromFile(FileInfo info
    , ref ValidationResult validationResult){
    //read the file and get DataTable
    iClassB.ConvertToRequest(dataTableResult, ref validationResult);
  }
}

public class ClassB : IClassB{
  public IEnumerable<Request> ConvertToRequest(DataTable dt
    , ref ValidationResult validationResult){
    foreach(DataRow row in dt.Rows){
      // convert to flat request first, to avoid reading DataTable too much
      iClassC1.Validate(rawRequest, ref validationResult);
      iClassC2.Validate(rawRequest, ref validationResult);
    }
    if(validationResult.IsSuccess){
      // convert and return the header-detail entity object
    }
  }
}

N.B: Please ignore the logic architecture (ex: about not throwing exception during validation, etc)

Upvotes: 1

Views: 200

Answers (2)

Steven
Steven

Reputation: 172865

I think you misunderstand the term "unit testing". Unit testing means testing classes in isolation. In your case you should do that by passing fake dependencies into the class to test. If you don't use fake dependencies in the classes you test, you are not testing those classes in isolation and you are therefore not doing unit testing. What you're doing in that case is integration testing.

So what you should do is unit test ALL classes and since you're practicing dependency injection, it should be very easy to fake out a classes dependencies under test.

Upvotes: 4

Morten
Morten

Reputation: 3854

You should always mock all outside influences, so you test the functionality of one thing and one thing only. It may require a lot of mocking, but that is not really an issue with all the available mocking frameworks out there (such as Rhinomocks, Moq and many others).

Following that rule, you should always:

  • Mock IClassB when testing ClassA
  • Mock IClass1 and IClass2 when testing ClassB

If you do not mock injected objects, you will get confusing test failures, during refactorings. Further, your tests will be integration tests and not unit tests, as they depend on the implemetation of outside classes.

Example: You are testing ClassA in the ClassATesFixture. Instead of a Mock of IClassB you decide to use the production code ClassB as input. The test is OK. Now, you refactor ClassB, and introduce an error. This will result in a testfailure in ClassATesFixture, although nothing in ClassA has changed.

So, if you use real objects as intput in your tests, you are actually testing much more than just the object you set out to test. On top of that, you will also get confusing testfailures.

Ideally, no test should go from green to red, unless something in the tested class has changed. Mocking is the way to achieve this goal.

Upvotes: 4

Related Questions