Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Generics for Return Type and Parameter

Tags:

c#

generics

I am writing a lot of unit tests and due to the specifics of our framework, each one needs this mock which uses DbSet and some type. The only difference is the type, so I would like to avoid repeating the same method many times and if possible have one (maybe) generic method. Using EF 6, .Net 4.7.1

Here is what I have now:

private Mock<DbSet<MyClass>> MockSetupForDbSet(List<MyClass> expected)

    {

        var mockDbSet = new Mock<DbSet<MyClass>>();



        mockDbSet.As<IQueryable<MyClass>>()

            .Setup(m => m.Provider)

            .Returns(new TestDbAsyncQueryProvider<MyClass>(expected.AsQueryable().Provider));



        mockDbSet.As<IQueryable<MyClass>>().Setup(m => m.Expression).Returns(expected.AsQueryable().Expression);



        return mockDbSet;

    }

And this is what I need:

private Mock<DbSet<T>> MockSetupForDbSet(List<T> expected) where T : class

    {

        var mockDbSet = new Mock<DbSet<T>>();



        mockDbSet.As<IQueryable<T>>()

            .Setup(m => m.Provider)

            .Returns(new TestDbAsyncQueryProvider<T>(expected.AsQueryable().Provider));



        mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(expected.AsQueryable().Expression);



        return mockDbSet;

    }

Is this the proper way or should I use another approach, e.g. dynamic parameter?

----- EDIT -----

Here is the final version of the generic method, thanks to the help from StackOverflow members (in case it helps someone in future):

internal static Mock<DbSet<T>> MockSetupForDbSet<T>(List<T> expected) where T : class

        {

            var mockDbSet = new Mock<DbSet<T>>();



            mockDbSet.As<IQueryable<T>>()

                .Setup(m => m.Provider)

                .Returns(new TestDbAsyncQueryProvider<T>(expected.AsQueryable().Provider));



            mockDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(expected.AsQueryable().ElementType);



            mockDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(expected.AsQueryable().GetEnumerator());



            mockDbSet.As<IDbAsyncEnumerable<T>>()

                .Setup(m => m.GetAsyncEnumerator())

                .Returns(new TestDbAsyncEnumerator<T>(expected.GetEnumerator()));



            mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(expected.AsQueryable().Expression);



            return mockDbSet;

        }

The test is written based and depends on Microsoft documentation 'Testing with a mocking framework": https://learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/mocking#async

like image 649
st_stefanov Avatar asked Jan 28 '26 00:01

st_stefanov


1 Answers

Include the generic type argument

                                This
                                 |
                                 V
Mock<DbSet<T>> MockSetupForDbSet<T>(List<T> expected) where T : class {
    //...omitted for brevity
}

provided the function is not already part of a generic class

class MyClass<T> {
    Mock<DbSet<T>> MockSetupForDbSet(List<T> expected) where T : class {
        //...omitted for brevity
    }
}
like image 165
Nkosi Avatar answered Jan 31 '26 03:01

Nkosi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!