I’m creating a CSV reader (yes I know about Fast CSV Reader and FileHelpers). The CsvReader class uses the CsvParser class to parse the CSV file. I want to make the CsvReader class unit testable, so I want to be able to externally set the CsvParser class that is used (also, so you can create your own implementation). I also, don’t want to have to create a parser and pass it in on normal use.
This is how I would like to use it.
var reader = new CsvReader( "path/to/file.csv" );
When doing this, I could create the CsvParser in the constructor of the CsvReader and have a property to change the parser.
public ICsvParser Parser { get; set; }
public CsvReader( filePath )
{
Parser = new CsvParser( filepath );
}
But then when unit testing, the default parser is always created and I only want to test the CsvReader.
The parser could be passed into the constructor, but I don’t want to have to create a parser separately on normal use. This seems like a good place for a factory.
This seems like it would be a common problem when using IOC. What is a good solution for this?
The solution is to rewrite your constructor of
CsvReaderto accept an implementation ofICsvParserand your concrete implementation ofICsvParsershould have a constructor taking in its dependencies (a path to a file to parse) and an already constructedICsvParsershould be injected into the constructor forCsvReader:The
ICsvParsershould already be constructed to accept its dependency (a path to the file to be parsed).Thusly:
The point is that
CsvReaderdoes not need a path, it just needs aCsvParser. Further,CsvReadershould not need to be aware of the dependencies ofCsvParser(that it needs a path to a file to parse) lest it becomes dependent on those dependencies too.newinside of constructors is a smell.