How to mock Db connection in xunit?

送分小仙女□ 提交于 2021-01-28 13:45:05

问题


I am writing unit test cases in xUnit. I am writing unit test case for opening database connection. I am writing negative case when database is down.

Below is the real code where I am making connection to database.

 public IDbConnection CreateDirectDb2Connection(int attempt = 0)
    {
      try
      {
        var conn = new DB2Connection(BuildDB2ConnectionString());
        conn.Open();
        return conn;
      }
      catch (Exception ex)
      {
        logService.Debug($"Failed to create and open a connection, attempt {attempt + 1}/3, error: {ex}");
        if (attempt < 2)
        {
          // Retry twice
          return CreateDirectDb2Connection(attempt + 1);
        }

        throw ex;
      }
    }   

Below is my xUnit test case code.

 public class ContextProviderServiceTests
    {
    private readonly IContextProviderService contextProvider = Substitute.For<IContextProviderService>();
    private readonly IDbCommand db2Command;
    private readonly MainframeDirectAccessRepository mainframeRepository;
    private readonly IDbConnection db2Connection;
      public ContextProviderServiceTests()
       {
          db2Connection = Substitute.For<IDbConnection>();
      db2Command = Substitute.For<IDbCommand>();
      db2Command.Parameters.Returns(Substitute.For<IDataParameterCollection>());
      db2Command.CreateParameter().Returns(Substitute.For<IDbDataParameter>());

      commandParameters = new List<TestDataParameter>();
      db2Command.Parameters.When(x => x.Add(Arg.Any<object>()))
        .Do(c => commandParameters.Add(new TestDataParameter
          {
            Name = c.Arg<IDbDataParameter>().ParameterName,
            Value = c.Arg<IDbDataParameter>().Value,
            DbType = c.Arg<IDbDataParameter>().DbType
          }));
     }
    [Fact]
    public void CreateDirectDb2ConnectionFailure()
    {
      var connection = mockProvider.GetDependency<IContextProviderService();
      connection.CreateDirectDb2Connection().Returns("I am not sure what to 
      return here");
    }

Can someone help me to write negative unit test case(When DB is down)? Any help would be appreciated. Thanks


回答1:


You should adhere to Interface Segregation and Dependency Inversion principle by using Inversion of Control with the help of Dependency Injection.

This way, you can create a MockDB2Connection, which you inject into the constructor, in your unit tests, while in your real code, you pass a proper DB2Connection.

Assume you have a service like this:

public class SomeService
{
    private readonly IDbConnection _dbCOnnection;

    public SomeService(IDbConnection dbConnection)
    {
        _dbCOnnection = dbConnection;
    }

    public async Task<IEnumerable<Foo>> GetFoos()
    {
        // Obviously don't do this in production code;
        // just for demonstration purposes.
        await _dbCOnnection.OpenAsync();
    }
}

You can implement Mock-connection classes like this:

public interface IDbConnection
{
    Task OpenAsync();

    // Other required methods...
}

public class ThrowingDbConnection : IDbConnection
{
    public Task OpenAsync()
    {
        throw new Exception("...");
    }
}

public class FakeDbConnection : IDbConnection
{
    public Task OpenAsync()
    {
        return Task.CompletedTask;
    }
}

As IoC container, you have multiple choices. Microsoft's Microsoft.Extensions.DependencyInjection, AutoFac, CastleWindsor, Ninject and so on. Pick the one that suits your needs. Most of the cases, Microsoft's or AutoFac should be good choices here.



来源:https://stackoverflow.com/questions/54746780/how-to-mock-db-connection-in-xunit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!