I'm pretty new to c# (and fwiw, moq) and I'm trying learn our product by writing unit tests. We have the following method in a database repository class:
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using Dapper;
using Newtonsoft.Json;
using Serilog;
public bool UpdateInactiveWidgets(List<Widgets> widgets)
{
int rowsUpdated;
using (var conn = new SqlConnection(connectionString))
{
rowsUpdated= conn.Execute(@"UPDATE dbo.Widgets
SET [Status] = 'Inactive'
WHERE ID = @ID", widgets);
}
return rowsUpdated == widgets.Count ? true : false;
}
I'd like to write a unit test for this, but I can't seem to get the mock connection going. Based on other posts about mocking a connection, I've added the following to my unit test:
[Fact]
public void Update_Inactive_Widgets()
{
var repo = new WidgetRepository();
var inActiveWidgets = new List<Widgets>()
{ //logic to create 2 widgets };
var connectionMock = new Mock<IDbConnection>();
connectionMock.Setup(m => m.Execute(It.IsAny<string>(),It.IsAny<object>(),null,null,null)).Returns(2);
var result = repo.UpdateInactiveWidgets(inActiveWidgets );
Assert.Equal(inActiveWidgets.Count,result);
The unit test fails on the connectionMock.Setup line with this error:
System.NotSupportedException: 'Unsupported expression: m => m.Execute(It.IsAny(), It.IsAny(), null, null, null) Extension methods (here: SqlMapper.Execute) may not be used in setup / verification expressions.'
I've found this article and am still making my way through to see how I can apply the points to my example: https://taurit.pl/moq-extension-methods-may-not-be-used-in-setup-verification-expressions/
But if you have any suggestions I'd appreciate it. I apologize in advance if I'm missing something basic.
Edit 2
If I made the connection a global variable in the class... and move the logic that connects outside the method under test would that help?
Sample pseudocode:
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using Dapper;
using Newtonsoft.Json;
using Serilog;
public UpdateInactiveWidgets()
{
var _conn;
}
public Connect_db()
{
_conn = new SqlConnection(connectionString);
}
public DisConnect_db()
{
//some logic to kill the db connection?
}
public bool UpdateInactiveWidgets(List<Widgets> widgets)
{
int rowsUpdated;
//would the using() still be applicable?
using (_conn)
{
rowsUpdated= _conn.Execute(@"UPDATE dbo.Widgets
SET [Status] = 'Inactive'
WHERE ID = @ID", widgets);
}
return rowsUpdated == widgets.Count ? true : false;
}