How to Moq a SqlConnection: wrap at SqlConnection in a protected virtual method that has a return type of IDbConnection, so that it can be setup from its mocked parent class.
We're doing a similar thing as the accepted answer, but exclusively with Moq (and Moq.Protected).
In your data repository class break-out your connection into it's own function. In this example, it's called GetConnection. Make this a protected virtual method so we can mock it later. And add a return type of IDbConnection. This is the key.
public Stuff FindValueMethod(string product)
{
...
try
{
using (var connection = GetConnection())
{
var result = await FindValue(connection, params);
//Do stuff
}
return stuff;
}
...
protected virtual IDbConnection GetConnection()
{
return new SqlConnection(injectedSettings.connectionString)
}
Later, in the data repository unit tests, do the dependency injection as you normally would, but wrap your dependencies with "Mock<>".
In order to mock protected virtual classes, we need them to be extensible from the main DataRepository class. So we also have to mock the data repo. Be sure to add a mock database connection, too.
using Moq;
using Moq.Protected;
...
private readonly Mock<DbConnection> _connection;
private readonly Mock<ILogger<DataRepository>> _logger;
private readonly Mock<Param> _param;
private readonly Mock<DataRepository> _dataRepository;
...
DataRepositoryTestsConstructor()
{
_connection = new Mock<DbConnection>();
_logger = new Mock<ILogger<DataRepository>>();
_param = new Mock<Param>();
//use the Mock.Object for dependency injections into the Mock repo.
_dataRepository = new Mock<DataRepository>(_logger.Object, _param.Object);
}
...
[Fact]
public async Task FindValueMethod_Returns_ProductPrice()
{
//Arrange
_dataRepository.Protected().Setup<IDbConnection>("GetConnection").Returns(_connection.Object);
//Act
var result = await _dataRepository.Object.FindValueMethod("rhubarb");
//Assert
Assert.NotNull(result);
}
In the unit test above, once we have a mock data repository, then we can set up a protected method with a return type of IDbConnection. And return the Mock connection object. Now, the debugger will slide over the using (var connection = GetConnection())
line like butter.
It's a bit of work to mock the repo and the repo dependencies. And refactor your code to have a protected virtual database connection method. But that one-liner in the Arrange section is worth it.