Search code examples
unit-testingasp.net-corexunit

Is it pointless to implement IDisposable in unit tests?


I have the following unit tests for an extension method. Both tests share same object instantiation (IBinanceClient), so I did it in the constructor. It implements IDisposable, because IBinanceClient does too. The question is: is implementing IDisposable in unit tests really useful/a good practice?

I'm open-minded for any recommendations about the rest of the code as well, even tho it's not a lot.

using Binance.Net;
using Binance.Net.Interfaces;
using Binance.Net.Objects;
using XBot.Models.Strategies.Whore;
using CryptoExchange.Net.Authentication;
using System;
using Xunit;

namespace XBot.Tests
{
    public class NoobStrategyExtensionsTests : IDisposable
    {
        private readonly IBinanceClient _client;

        public NoobStrategyExtensionsTests()
        {
            _client = new BinanceClient(new BinanceClientOptions()
            {
                ApiCredentials = new ApiCredentials("-", "-"),
                AutoTimestamp = true,
                AutoTimestampRecalculationInterval = TimeSpan.FromMinutes(30)
            });
        }

        [Fact]
        public void CheckAndFillBNB_OneBNB_ReturnsTrue()
        {
            // Arrange

            // Act
            bool actual = _client.CheckAndFillBNB(1, true);

            // Assert
            Assert.True(actual);
        }

        [Theory]
        [InlineData(3, false)]
        [InlineData(1, true)]
        [InlineData(2, false)]
        [InlineData(1.99, true)]
        public void CheckAndFillBNB_MultipleBNBQuantities_ReturnsTrue(decimal input, bool expected)
        {
            // Arrange

            // Act
            bool actual = _client.CheckAndFillBNB(input, true);

            // Assert
            Assert.Equal(expected, actual);
        }

        public void Dispose()
        {
            if (_client != null)
                _client.Dispose();
        }
    }
}


Solution

  • No it is not pointless when you dispose your test. for instance, you have written an integration test and your test is going to examine database so it is helpful to close your database connection after it is run. Another reason is that when you have a large number of tests it is better after one test is run all resources be cleaned up as a result you get a better performance.

    Example: https://xunit.net/docs/shared-context

    Class Fixtures: When to use: when you want to create a single test context and share it among all the tests in the class, and have it cleaned up after all the tests in the class have finished.

    public class DatabaseFixture : IDisposable
    {
        public DatabaseFixture()
        {
            Db = new SqlConnection("MyConnectionString");
    
            // ... initialize data in the test database ...
        }
    
        public void Dispose()
        {
            // ... clean up test data from the database ...
        }
    
        public SqlConnection Db { get; private set; }
    }
    
    public class MyDatabaseTests : IClassFixture<DatabaseFixture>
    {
        DatabaseFixture fixture;
    
        public MyDatabaseTests(DatabaseFixture fixture)
        {
            this.fixture = fixture;
        }
    
        // ... write tests, using fixture.Db to get access to the SQL Server ...
    }