Search code examples
c#.netunit-testingnunitdbproviderfactories

Best way to unit test DbProviderFactory


I am trying to create Unit Test (NUnit) for the old code that we have.

We using DbProviderFactory to check if table exist in the database before doing anything with that table.

I know that this might look more like integration testing, but regardless of what you call it I need to have a test for it. I would prefer to use something self contained and not dependent on the database.

I tried to use excel as my data source but to select table in excel it should have $ after the table name which wouldn't work in my case because I don't want to modify my code to accommodate Unit Test.

How can I unit test following code?

static bool TableDoesNotExist(string tableName, string connectionString, string providerName = "System.Data.OleDb")
    {
        try
        {
            DbProviderFactory providerFactory = DbProviderFactories.GetFactory(providerName);

            using (DbConnection conn = providerFactory.CreateConnection())
            {
                conn.ConnectionString = connectionString;
                conn.Open();

                DbCommand cmd = providerFactory.CreateCommand();
                cmd.Connection = conn;

                string tblQuery = "";

                if (providerName == "System.Data.Odbc")
                    tblQuery = string.Format("SELECT COUNT(*) FROM SYSTABLE WHERE TABLE_NAME = '{0}'", tableName);
                else
                    tblQuery = string.Format("SELECT COUNT(*) FROM [INFORMATION_SCHEMA.TABLES$] WHERE TABLE_NAME = '{0}'", tableName);

                cmd.CommandText = tblQuery;

                Console.WriteLine(cmd.CommandText);

                DbDataReader dr = cmd.ExecuteReader();

                DataTable dt = new DataTable();
                dt.Load(dr);

                if (dt.Rows.Count == 1 && Convert.ToInt32(dt.Rows[0][0]) == 0)
                {
                    return true;
                }


            }

            return false;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        return false;
    }

Any help would be appreciated.


Solution

  • You can try using Stubs once. I have written a simple test case using Stub. It's working as expected. Here is the code:

        [TestMethod]
        public void Test01()
        {
            using (ShimsContext.Create())
            {
                var dbConnectionOpened = false;
                var fakeConnection = new StubDbConnection()
                {
                    Open01 = () => { dbConnectionOpened = true; }
                };
                var fakeCommand = new StubDbCommand()
                {
                    ExecuteDbDataReaderCommandBehavior = (com) => GetFakeReader()
                };
                var fakeDbProviderFactory = new StubDbProviderFactory()
                {
                    CreateConnection01 = () => fakeConnection,
                    CreateCommand01 = () => fakeCommand
                };
                ShimDbProviderFactories.GetFactoryString = (arg1) => fakeDbProviderFactory;
    
                var val = SqlConnectionFactory.TableDoesNotExist("testTable", "conn");
                Assert.IsTrue(dbConnectionOpened);
                Assert.IsTrue(val);
            }            
        }
    
        private DbDataReader GetFakeReader()
        {
            const int count = 0;
            var dt = new DataTable("Test-Table");
            dt.Columns.Add(new DataColumn("Count"));
            dt.Rows.Add(count);
            return dt.CreateDataReader();
        }
    


    You can play around with the GetFakeReader() method to Unit Test various scenarios.