Codehelp
Codehelp

Reputation: 4747

Testing Repository update or insert using Moq

I have a method like this:

public int InsertOrUpdateCustomer(Customer customer)
{
var result = default(int);
try
{
    using (var customerContext = new Customer())
    {
        var customerResult = customerContext.UpdateGraph(coupon, map => map.OwnedCollection(p => p.CustomerPoints));
        couponsContext.SaveChanges();
        result = customerResult.CustomerTypeID;
    }
}
catch (Exception ex)
{
    // Log the Exception
}
return result;
}

It creates an instance of CustomerContext, Saves, and returns the new CustomerID.

I am trying to use Moq for this and have this method where the test needs to check for a integer value being returned.

[TestMethod]
public void Inserting_A_Customer_Should_Return_A_IntegerValue(Customer customer)
{
    var mock = new Mock<ICustomerRepository>();
    int customerId = 1;
    mock.Setup(c => c.InsertOrUpdateCustomer(customer)).Returns(new Customer() { Id = customerId });
}

That gives this error:

cannot convert from 'Entities.Commerce.Customer' to 'System.Func<int>'

I am also new to Moq.

What I would like to know from this question is, if one has a code like above, how does one proceed with writing Unit Tests.

It would be of great help if some pointers are given in getting to know that process.

Thanks in advance.

Upvotes: 2

Views: 2844

Answers (1)

StuartLC
StuartLC

Reputation: 107267

The error itself is because the method you are setting up is of this signature:

public int InsertOrUpdateCustomer(Customer customer)

Whereas your setup is trying to return a customer

 mock.Setup(c => c.InsertOrUpdateCustomer(customer))
     .Returns(new Customer() { Id = customerId });

Changing this to return a fake int such as .Returns(42); will avoid the error.

The not so good news is if the purpose of the test is Inserting_A_Customer_Should_Return_A_IntegerValue that you will be mocking the very thing you are trying to test (you would just be testing Moq).

What you need to do is Moq out your DbContext, which makes this line problematic, given its tight coupling:

 using (var customerContext = new CustomerContext())

The suggestion here is to either allow the DbContext to be injected into the constructor of your class you are testing (or inject a factory interface which can create a DbContext).

You can then Mock the DbContext and the relevant IDbSets (Customers) as per this MSDN article here, which you can then inject into your class being tested, and test any logic / branching in your class.

Upvotes: 2

Related Questions