Search code examples
c#sqliteunit-testing

How to skip database part in constructor from unit test?


I want to perform a unit test for the function calTax(), and I don't want the database part in the constructor for it.

Since constructor is called automatically, I get this error:

"SQLite Error 1: 'no such table: Products_t'."

Is there any way to skip the database part in the constructor call from the unit test execution or to avoid this error?

Class Code:

//constructor
public OrderVM()
{
    using (var db = new DatabaseContext())
    {
        var list = db.Products_t.ToList();
        Products_o = new ObservableCollection<Product>(list);
    }             
}


//function I want to test
public void calTax()
{
    Tax = SubTotal * 5/ 100;
}

Unit Test Code:

public class UnitTest1
{
    [Fact]
    public void Calculate_Tax()
    {
        var order = new OrderVM();
        order.SubTotal = 100;
        order.calTax();
        order.Tax.Should().Be(5);
    }
}

Solution

  • Either use dependency injection or pass in the list directly. In any case, you need to remove the dependency on the DatabaseContext:

    public OrderVM(List<Product> products)
    {
        Products_o = new ObservableCollection<Product>(products);
    }
    
    public void calTax()
    {
        Tax = SubTotal * 5/ 100;
    }
    

    Then you can test the calTax() method by passing a List<Product>, which might also be an empty list in certain scenarios:

    public class UnitTest1
    {
        [Fact]
        public void Calculate_Tax()
        {
            var order = new OrderVM(new List<Product>());
            order.SubTotal = 100;
            order.calTax();
            order.Tax.Should().Be(5);
        }
    }
    

    If you need more flexibility or you cannot pass an argument to the OrderVM constructor for some reason, you may want to familiarize yourself with Dependency Injection (DI) and Inversion of Control (IoC).