简体   繁体   中英

Unit Test Static methods in a class using MS Fakes C#

Here is the class I am trying to mock. Helper class that has a static method. Which takes in a dataTable.

public class DataTableHelpers
    {
        public static ArrayList GetDataTableColumns(DataTable dataTable)
        {
            if (dataTable == null)
            {
                throw new ArgumentNullException(nameof(dataTable));
            }

            var columnsCount = dataTable.Columns.Count;
            var columnHeadings = new ArrayList();
            for (var i = 0; i < columnsCount; i++)
            {
                var dataColumn = dataTable.Columns[i];
                columnHeadings.Add(dataColumn.ColumnName.ToString());
            }
            return columnHeadings;
        }
    }

Tried using ShimsContext. Here is the snippet I have come up with. Want to mock when datatable is null and not null.

public void GivenDatatableIsNUllShouldThrowNullException()
        {
            var expected = new ArrayList();
            //ARRANGE
            using (ShimsContext.Create())
            {
                dataTableHelpers = new DataTableHelpers();

                //ACT

                var result = ShimDataTableHelpers.GetDataTableColumnsDataTable = (s) =>
                {
                    Should.Throw<ArgumentNullException>(() =>
                    {
                    });
                    throw new ArgumentNullException(nameof(s));
                };
                //Assert

                Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AreNotEqual(result, expected);
            }
        }

Your question is a little unclear but I think what you're after is a way to test code that is using the given static helper method. It's easy to test the static helper, it's not so easy to test code that's using those helpers. When you run into something like I've found it best to refactor that code to not use static helpers. Instead push that code into a class that you can abstract and inject into places you need it. But sometimes that's easier said than done.

As a stop gap you can incrementally move to that direction by introducing a class to hold the actual code that you can then swap out when testing. This doesn't use MS Fakes but it's a technique that you can use to help make your code more testable.

I'm sorry I can't recall who first came up with this method, it certainly wasn't me. But here's the idea:

Create a class to hold the logic:

public class DataTableHelperImpl : IDataTableHelperImpl
{
    public ArrayList GetDataTableColumns(DataTable dataTable)
    {
        if (dataTable == null)
        {
            throw new ArgumentNullException(nameof(dataTable));
        }

        var columnsCount = dataTable.Columns.Count;
        var columnHeadings = new ArrayList();
        for (var i = 0; i < columnsCount; i++)
        {
            var dataColumn = dataTable.Columns[i];
            columnHeadings.Add(dataColumn.ColumnName.ToString());
        }
        return columnHeadings;
    }
}

With the associated interface that you can then mock:

public interface IDataTableHelperImpl
{
    public ArrayList GetDataTableColumns(DataTable dataTable);
}

Then use this in your static helper:

public static class Helper
{
    public static IDataTableHelperImpl implementation = new DataTableHelperImpl();

    public static ArrayList GetDataTableColumns(DataTable dataTable)
    {
        return implementation.GetDataTableColumns(dataTable);
    }
}

Now in your test you can swap out that class to mock whatever behavior you want.

    [Fact]
    public void Test1()
    {
        var implMock = Mock.Of<IDataTableHelperImpl>();

        Helper.implementation = implMock;

        // whatever you need to test...
    }

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