VansFannel
VansFannel

Reputation: 45911

Using generics in lambda expression or how to access a dbset with generics

I'm developing a Test project with NUnit, Moq, C# and .NET Framework 4.7.

I have these two methods that are almost equals:

using Microsoft.EntityFrameworkCore;
using Moq;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;

private void MockProducts(Mock<TRZFDbContext> mockContext, List<Product> data)
{
    IQueryable<Product> queryable = data.AsQueryable();

    var mockSet = new Mock<DbSet<Product>>();

    mockSet.As<IQueryable<Product>>().Setup(m => m.Provider).Returns(queryable.Provider);
    mockSet.As<IQueryable<Product>>().Setup(m => m.Expression).Returns(queryable.Expression);
    mockSet.As<IQueryable<Product>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
    mockSet.As<IQueryable<Product>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
    mockSet.Setup(d => d.Add(It.IsAny<Product>())).Callback<Product>((s) => data.Add(s));
    mockSet.Setup(d => d.Remove(It.IsAny<Product>())).Callback<Product>((s) => data.Remove(s));

    mockContext.Setup(m => m.Product).Returns(mockSet.Object);
}

private void MockEmvoProducts(Mock<TRZFDbContext> mockContext, List<EmvoProduct> data)
{
    IQueryable<EmvoProduct> queryable = data.AsQueryable();

    var mockSet = new Mock<DbSet<EmvoProduct>>();

    mockSet.As<IQueryable<EmvoProduct>>().Setup(m => m.Provider).Returns(queryable.Provider);
    mockSet.As<IQueryable<EmvoProduct>>().Setup(m => m.Expression).Returns(queryable.Expression);
    mockSet.As<IQueryable<EmvoProduct>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
    mockSet.As<IQueryable<EmvoProduct>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
    mockSet.Setup(d => d.Add(It.IsAny<EmvoProduct>())).Callback<EmvoProduct>((s) => data.Add(s));
    mockSet.Setup(d => d.Remove(It.IsAny<EmvoProduct>())).Callback<EmvoProduct>((s) => data.Remove(s));

    mockContext.Setup(m => m.EmvoProduct).Returns(mockSet.Object);
}

I can create a generics method changing the second argument data with a generic. But my problem is on the last sentence:

mockContext.Setup(m => m.Product).Returns(mockSet.Object);

and

mockContext.Setup(m => m.EmvoProduct).Returns(mockSet.Object);

m.Product is a DbSet of Product and m.EmvoProduct is a DbSet of EmvoProduct.

Is there a way to make the lambda expression uses the generics? Or maybe there are another approaches.

Upvotes: 0

Views: 79

Answers (1)

Neville Nazerane
Neville Nazerane

Reputation: 7019

You should be able to do so with an extension function that is declared something like this in a public static class

public static class DBSetExtensions {

    public static void Setup<T>(this DbSet<T> list, Action<T> lamda){
        lamda(objectFromDbSet);
    }

}

Now in any class you have a DbSet with generics you should be able to use

mockSet.Setup(d => d.Add(It.IsAny<EmvoProduct>()))

For the chained function Callback, you need to change the return type on the function above from void to whatever object they return in setup.

Upvotes: 1

Related Questions