Executing my Class Function via Dependency Injection

Viewed 2158

I have been working on converting my tightly coupled method into one that can be unit tested and have sought some advice on here. I now have my method passing its unit test thanks to some advice - however I now find that I cant call the method from my application. I used to access my GetAllProductsFromCSV() method from the controller with the following:

    public ActionResult Index()
    {
        var products = new ProductsCSV();
        List<ProductItem> allProducts = products.GetAllProductsFromCSV();

        foreach (var product in allProducts)
        {
            if (string.IsNullOrEmpty(product.ImagePath))
            {
                product.ImagePath = "blank.jpg";
            }
        }

        return View(allProducts);
    }

The Method was as follows:

public class ProductsCSV
{
    public List<ProductItem> GetAllProductsFromCSV()
    {
        var productFilePath = HttpContext.Current.Server.MapPath(@"~/CSV/products.csv");

        String[] csvData = File.ReadAllLines(productFilePath);

        List<ProductItem> result = new List<ProductItem>();

        foreach (string csvrow in csvData)
        {
            var fields = csvrow.Split(',');
            ProductItem prod = new ProductItem()
            {
                ID = Convert.ToInt32(fields[0]),
                Description = fields[1],
                Item = fields[2][0],
                Price = Convert.ToDecimal(fields[3]),
                ImagePath = fields[4],
                Barcode = fields[5]
            };
            result.Add(prod);
        }
        return result;
    }
}

I have now made the following changes in the ProductCSV class:

public class ProductsCSV
{
    private readonly IProductsCsvReader reader;

    public ProductsCSV(IProductsCsvReader reader = null)
    {
        this.reader = reader;
    }

    public List<ProductItem> GetAllProductsFromCSV()
    {
        var productFilePath = @"~/CSV/products.csv";
        var csvData = reader.ReadAllLines(productFilePath);
        var result = parseProducts(csvData);
        return result;
    }


    private List<ProductItem> parseProducts(String[] csvData)
    {
        List<ProductItem> result = new List<ProductItem>();

        foreach (string csvrow in csvData)
        {
            var fields = csvrow.Split(',');
            ProductItem prod = new ProductItem()
            {
                ID = Convert.ToInt32(fields[0]),
                Description = fields[1],
                Item = fields[2][0],
                Price = Convert.ToDecimal(fields[3]),
                ImagePath = fields[4],
                Barcode = fields[5]
            };
            result.Add(prod);
        }
        return result;
    }

Along with the following class & Interface:

public class DefaultProductsCsvReader : IProductsCsvReader
{
    public string[] ReadAllLines(string virtualPath)
    {
        var productFilePath = HostingEnvironment.MapPath(virtualPath);
        String[] csvData = File.ReadAllLines(productFilePath);
        return csvData;
    }
}

public interface IProductsCsvReader
{
    string[] ReadAllLines(string virtualPath);
}

As I said, the Unit-Test on method GetAllProductsFromCSV completes successfully now however when I try accessing the method from my controller I get a NullReferenceException on the reader.ReadAllLines call within GetAllProductsFromCSV. It makes sense to me that when I attempt to create an instance of ProductsCSV from within the controller - I am not passing in any parameters... The constructor for the class however requests a IProductsCsvReader. What I cant figure out is how do I actually make the call to the method now? I hope that is clear??

1 Answers
Related