简体   繁体   中英

How to mock Db connection in xunit?

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM