I have written a method that gets data from the database using DbContext.Database.SqlQuery() (EF6.1):
internal List<WorkOrderLine> Get()
{
var sql = GetSql();
var workOrders = Context.Database.SqlQuery<Model.Analysis.WorkOrder>(sql).ToList();
return workOrders.Select(workOrder => new WorkOrderLine
{
Id = workOrder.a,
Title = workOrder.b,
Status = workOrder.c,
Location = workOrder.d,
AssignedTo = workOrder.e,
StartDate = workOrder.f,
DueDate = workOrder.g,
CompletedDate = h
}).ToList();
}
I want to write a unit test for the method and check that the expected SQL is passed into SQLQuery and then to pass back a list of data so that it can be processed via the rest of the method so that I can check the output.
I believe the correct/best approach would be to mock the DbContext and pass this mocked context into the class instead of a real context. If so, I think I might be able to do this with one of the following:
Use Moq
Manually create a mock to carry out the tests and return the data
Is using mocks the correct technique?
If so, which of these 2 options is the simplest/best?
P.S. I usually use Effort when testing with EF but it doesn't handle this method.
EDIT:
Here is the complete class:
internal Report(MyContext context, ChartWidgetFilter filters, string ownerEntityFilter)
: base(context, filters, ownerEntityFilter)
{
}
internal List<WorkOrderLine> Get()
{
var sql = GetSql();
var workOrders = Context.Database.SqlQuery<Model.Analysis.WorkOrder>(sql).ToList();
return workOrders.Select(workOrder => new WorkOrderLine
{
Id = workOrder.a,
Title = workOrder.b,
Status = workOrder.c,
Location = workOrder.d,
AssignedTo = workOrder.e,
StartDate = workOrder.f,
DueDate = workOrder.g,
CompletedDate = h
}).ToList();
}
private string GetSql()
{
//return the sql generated using the filters and ownerEntityFilter
//parameters passed into the constructor
}
}
EDIT 2:
The two things that I need to test are that:
GetSql() creates the correct SQL for the parameters passed into the constructor - ChartWidgetFilter filters, string ownerEntityFilter
That the return workOrders.Select... statement returns a correctly mapped list of WorkOrderLine objects for a list of Model.Analysis.WorkOrder objects
Here is a example about how to "mock" for a unit test
public class SolvencyBllTest
{
private MyAttBLL myAttBll;
private readonly List<AttestationEntity> attestationsFakeForTest = new List<AttestationEntity>
{
/// ... Build the child object , used for 'mock'
}
//Initialize event => here we define what the 'mock' should to de when we use the [GetListWithChildren] function
[TestInitialize]
public void Setup()
{
var mockedAttestationFakeToTest = new Mock<IAttestationDataAccessLayer>();
//setup GetAll : return the whole list
mockedAttestationFakeToTest
.Setup(attestation => attestation.GetListWithChildren(It.IsAny<Expression<Func<AttestationEntity, bool>>>()))
.Returns((Expression<Func<AttestationEntity, bool>> expression) =>
{
return this.attestationsFakeForTest.AsQueryable().Where(expression);
});
this.myAttBll = new MyAttBLL(attestationsCertificatesRefundDal: null, attestationDal: mockedAttestationFakeToTest.Object, emailNotifier: mockedEmailNotifier.Object);
}
[TestMethod]
public void SolvencyBllTest_CheckAttestation()
{
// Initalize the result
SolvencyCheckResult solvencyCheckResult = new SolvencyCheckResult()
{
solvency = new SolvencyModel()
};
// Declare and initializes our object which encapsulates our parameters for the solvency check
SolvencyCheckParameters solvencyCheckParams = new SolvencyCheckParameters(TestConstants.Contact.LAST_NAME, TestConstants.Contact.FIRST_NAME, TestConstants.Contact.BIRTH_DATE, TestConstants.Address.STREET, TestConstants.Address.ZIPCODE, TestConstants.UNIT_TEST_USER);
// this (solvencyBll) will not try to find in the database but in the collection with just mock before
// Try to retrieve all certificates dating back 3 months and have the same name + first name + date of birth
List<AttestationModel> attsLatestToCheck = this.myAttBll.CheckLatestAttestation(solvencyCheckResult, solvencyCheckParams);
// 1 attestation created today => OK
// 1 attestation created 1 month ago => OK
// 1 attestation created 2 month ago => OK
// 1 attestation created 4 month ago => KO
Assert.AreEqual(3, attsLatestToCheck.Count);
}
Example for use the dbContext from the BLL part functions
public IEnumerable<AttestationEntity> GetListWithChildren(Expression<Func<AttestationEntity, bool>> pred)
{
using (ScDbContext context = new ScDbContext())
{
return this.GetListWithChildrenInternal(context, pred).OrderBy(att => att.CreatedDate).ToList();
}
}
internal IEnumerable<AttestationEntity> GetListWithChildrenInternal(ScDbContext context, Expression<Func<AttestationEntity, bool>> pred)
{
return this.GetListInternal(context, pred, attestationChildren).OrderBy(att => att.CreatedDate).ToList();
}
internal IEnumerable<E> GetListInternal(DBC context, Expression<Func<E, bool>> where, params Expression<Func<E, object>>[] navigationProperties)
{
IQueryable<E> dbQuery = context.Set<E>();
//Apply eager loading
foreach (Expression<Func<E, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<E, object>(navigationProperty);
return dbQuery
//.AsNoTracking() //Don't track any changes for the selected item
.Where(where)
.ToList(); //Apply where clause
}
Related
I have a delete method that takes in an IEnumerable of Ids that are of type string, and have a filter taking in those ids using Filter.In. However when passing in a set of ids I am getting a count of 0 for records deleted. Is my filter causing the issue?
I've created a test method to test my delete method and am passing in ids to try and have them deleted.
Test Solution
MongodDB Test method for delete method
[Theory]
[InlineData(1)]
[InlineData(100)]
public async void TEST_DELETE(int quantity)
{
using (var server = StartServer())
{
// Arrange
var collection = SetupCollection(server.Database, quantity);
var dataUtility = new MongoDataUtility(server.Database,
MongoDbSettings);
var service = new MongoDatabaseService(dataUtility, Logger);
var items =
collection.FindSync(FilterDefinition<BsonDocument>.Empty)
.ToIdCollection();
_output.WriteLine(JsonConvert.SerializeObject(items,
Formatting.Indented));
// Act
var result = await
dataUtility.DeleteIdentifiedDataAsync(items, CollectionName);
_output.WriteLine(JsonConvert.SerializeObject(result,
Formatting.Indented));
// Assert
Assert.True(result.DeletedCount.Equals(items.Count));
}
}
Setup collection
public IMongoCollection<BsonDocument> SetupCollection(IMongoDatabase db,
int quantity)
{
var collection = db.GetCollection<BsonDocument>(CollectionName);
AddCreateDateIndex(collection);
SeedData(collection, quantity);
return collection;
}
Seed data
public void SeedData(IMongoCollection<BsonDocument> collection, int?
quantity = null)
{
if (quantity != null && quantity > 0)
{
collection.InsertMany(GenerateTestData((int)quantity));
}
}
Project
MongoDB delete method
public async Task<DeleteResult>
DeleteIdentifiedDataAsync(IEnumerable<ObjectId> ids, string Resource,
CancellationToken cancellationToken = default)
{
var collection = _db.GetCollection<BsonDocument>(Resource);
var filter = Builders<BsonDocument>.Filter.In("_id", ids);
if (ids != null && ids.Any() )
{
return await collection.DeleteManyAsync(filter,
cancellationToken);
}
return null;
}
Extensions
public static ICollection<ObjectId> ToIdCollection(this
IAsyncCursor<BsonDocument> #this)
{
return #this.Find(Builders<BsonDocument>.Filter.Empty)
.ToEnumerable()
.Select(s => s["_id"].AsObjectId)
.ToList();
}
Your ToIdCollection method gets all the ids but also converts them from ObjectId to String when you run .Select(dict => dict["_id"].ToString()). MongoDB compares both values and types when you run DeleteManyAsync and that's why there is no match - you're trying to compare list of strings against ObjectIds that are stored in the database.
To fix that you can replace ToIdCollection with following implementation:
return #this.Find(Builders<BsonDocument>.Filter.Empty)
.ToEnumerable()
.Select(s => s["_id"].AsObjectId)
.ToList()
Could some one please help me to resolved this? i'm trying to change CustomAsync to MustAsync, but i couldn't make things to work. Below is my custom method
RuleFor(o => o).MustAsync(o => {
return CheckIdNumberAlreadyExist(o)
});
private static async Task<ValidationFailure> CheckIdNumberAlreadyExist(SaveProxyCommand command)
{
if (command.Id > 0)
return null;
using (IDbConnection connection = new SqlConnection(ConnectionSettings.LicensingConnectionString))
{
var param = new DynamicParameters();
param.Add("#idnumber", command.IdNumber);
var vehicle = await connection.QueryFirstOrDefaultAsync<dynamic>("new_checkDuplicateProxyIdNumber", param, commandType: CommandType.StoredProcedure);
return vehicle != null
? new ValidationFailure("IdNumber", "Id Number Already Exist")
: null;
}
}
To make it work with the latest version of the FluentValidation, I had to use the codes like below.
RuleFor(ws => ws).MustAsync((x, cancellation) => UserHasAccess(x)).WithMessage("User doesn't have access to perform this action");
Please notice the lambda expression here MustAsync((x, cancellation) => UserHasAccess(x)), without this I was always getting an error as cannot convert from 'method group' to 'Func<Worksheet, CancellationToken, Task<bool>>
Below is my custom UserHasAccess function.
private async Task <bool> UserHasAccess(Worksheet worksheet) {
var permissionObject = await _dataProviderService.GetItemAsync(worksheet.FileItemId);
if (permissionObject is null) return false;
if (EditAccess(permissionObject.Permission)) return true;
return false;
}
I'm assuming you're using a version of FluentValidation prior to version 6, as you're not passing in a Continuation Token, so I've based my answer on version 5.6.2.
Your example code does not compile, for starters, as you're missing a semi-colon in your actual rule. You are also evaluating two different properties on the SaveProxyCommand parameter.
I've built a very small POC based on some assumptions:
Given 2 classes:
public class SaveProxyCommand {
public int Id { get; set; }
}
public class ValidationFailure {
public string PropertyName { get; }
public string Message { get; }
public ValidationFailure(string propertyName, string message){
Message = message;
PropertyName = propertyName;
}
}
And a validator:
public class SaveProxyCommandValidator : AbstractValidator<SaveProxyCommand>{
public SaveProxyCommandValidator()
{
RuleFor(o => o).MustAsync(CheckIdNumberAlreadyExists)
.WithName("Id")
.WithState(o => new ValidationFailure(nameof(o.IdNumber), "Id Number Already Exist"));
}
private static async Task<bool> CheckIdNumberAlreadyExists(SaveProxyCommand command) {
if (command.Id > 0)
return true;
var existingIdNumbers = new[] {
1, 2, 3, 4
};
// This is a fudge, but you'd make your db call here
var isNewNumber = !(await Task.FromResult(existingIdNumbers.Contains(command.IdNumber)));
return isNewNumber;
}
}
I didn't include the call to the database, as that's not part of your problem. There are a couple of things of note here:
You're not setting the .WithName annotation method, but when you're setting up a validation rule for an object you have to do this, as FluentValidation expects you to specify specific properties to be validated by default, if you pass in an entire object it just doesn't know how to report errors back.
Must/MustAsync need to return a bool/Task<bool> instead of a custom object. To get around this, you can specify a custom state to be returned when failing validation.
You can then get access to this like this:
var sut = new SaveProxyCommand { Id = 0, IdNumber = 3 };
var validator = new SaveProxyCommandValidator();
var result = validator.ValidateAsync(sut).GetAwaiter().GetResult();
var ValidationFailures = result.Errors?.Select(s => s.CustomState).Cast<ValidationFailure>();
The above does not take into account empty collections, it's just an example of how to dig into the object graph to retrieve custom state.
As a suggestion, fluentvalidation works best if you set up individual rules per property, instead of validating the entire object. My take on this would be something like this:
public class SaveProxyCommandValidator : AbstractValidator<SaveProxyCommand>{
public SaveProxyCommandValidator()
{
RuleFor(o => o.IdNumber).MustAsync(CheckIdNumberAlreadyExists)
.Unless(o => o.Id > 0)
.WithState(o => new ValidationFailure(nameof(o.IdNumber), "Id Number Already Exist"));
}
private static async Task<bool> CheckIdNumberAlreadyExists(int numberToEvaluate) {
var existingIdNumbers = new[] {
1, 2, 3, 4
};
// This is a fudge, but you'd make your db call here
var isNewNumber = !(await Task.FromResult(existingIdNumbers.Contains(numberToEvaluate)));
return isNewNumber;
}
}
This read more like a narrative, it uses the .Unless construct to only run the rule if Id is not more than 0, and does not require the evaluation of the entire object.
I have done fair bit research and tried all sorts of different ways of getting the Test to pass but now i need some help.
I am trying to test the following repository method:
public class PortalsRepository : BaseRepository<PortalDomainRole>, IPortalsRepository
{
public PortalsRepository(IAuthDbContext context) : base(context)
{
}
public IEnumerable<PortalRole> GetRoles(string domainName)
{
return Set.Include(x => x.PortalDomain)
.Include(x => x.PortalRole)
.Where(x => x.PortalDomain.Name.ToLower() == domainName)
.Select(x => x.PortalRole)
.ToList();
}
}
The Context looks like:
public interface IAuthDbContext : IDbContextBase
{
}
public interface IDbContextBase
{
IDbSet<T> Set<T>() where T : class;
IEnumerable<DbValidationError> GetEntityValidationErrors();
int SaveChanges();
Task<int> SaveChangesAsync();
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
My Unit Test Set-up Looks like:
protected override void GivenThat()
{
var mockRolesSet = GetMockDbSet(PortalRoles().AsQueryable());
mockRolesSet.Setup(x => x.Include("PortalRole")).Returns(mockRolesSet.Object);
var mockDomainsSet = GetMockDbSet(PortalDomains().AsQueryable());
mockDomainsSet.Setup(x => x.Include("PortalDomain")).Returns(mockDomainsSet.Object);
var mockPortalDomanRolesSet = GetMockDbSet(PortalDomainRoles().AsQueryable());
mockPortalDomanRolesSet.Setup(x => x.Include("PortalRole")).Returns(mockPortalDomanRolesSet.Object);
mockPortalDomanRolesSet.Setup(x => x.Include("PortalDomain")).Returns(mockPortalDomanRolesSet.Object);
var customDbContextMock = new Mock<IAuthDbContext>();
customDbContextMock.Setup(x => x.Set<PortalRole>()).Returns(mockRolesSet.Object);
customDbContextMock.Setup(x => x.Set<PortalDomain>()).Returns(mockDomainsSet.Object);
customDbContextMock.Setup(x => x.Set<PortalDomainRole>()).Returns(mockPortalDomanRolesSet.Object);
ClassUnderTest = new PortalsRepository(customDbContextMock.Object);
}
My Unit Test Supporting Methods:
public List<PortalDomainRole> PortalDomainRoles()
{
var data = new List<PortalDomainRole>
{
new PortalDomainRole { PortalRoleId = 2, PortalDomainId = 1},
new PortalDomainRole { PortalRoleId = 1, PortalDomainId = 2},
new PortalDomainRole { PortalRoleId = 2, PortalDomainId = 2}
};
return data;
}
public List<PortalDomain> PortalDomains()
{
var data = new List<PortalDomain>
{
new PortalDomain { Name = "google.co.uk", PortalDomainId = 1 },
new PortalDomain { Name = "bbc.com", PortalDomainId = 2 }
};
return data;
}
public List<PortalRole> PortalRoles()
{
var data = new List<PortalRole>
{
new PortalRole {Name = "New Products", PortalRoleId = 1},
new PortalRole {Name = "Classic Products", PortalRoleId = 2}
};
return data;
}
When the unit test executes the method in question, i get:
System.NullReferenceException : Object reference not set to an instance of an object.
Most likely it does not know how to handle the nested include statements - i have followed many online questions and tutorials and now i am stuck.
My answer is probably a bit controversial, but in my experience, the best way to test your repository layer (or whatever you call the code that does the actual data access), is by having it actually call the database during testing.
When you are writing your unit test, you are assuming that Entity Framework works in a specific way. But sometimes it works in different ways than you expect, and thus a test may pass, even though the code doesn't work correctly.
Take this example, that illustrates the problem (the last EF version I worked with was version 4, but I assume that my statement is still true for EF6)
public class Foo {
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool Active {
get { return StartDate < DateTime.Now && EndDate > DateTime.Now }
}
}
public class FooRepository {
public IEnumerable<Foo> ActiveFoos { get { return DataContext.Foos.Where(x => x.Active) } }
}
Testing this FooRepository against a mocked data access will pass, but executing against a real database will throw an exception. That is because EF will try to create an SQL clause for the Where(x => x.Active), but because Active is not a field in the database, EF will have no idea how to translate the query to SQL.
So your unit test provides a false positive. Executing the tests against the database will make it fail, as it should.
Compile just fine but execution fail with the error in the title.
ArtistService.cs
public class ArtistService : IArtistService
{
public List<Artist> ArtistDetail()
{
using (ArtistDataContext db = new ArtistDataContext())
{
return (from artist in db.Artists
select new Artist()
{
Id = artist.Id,
Artist_name = Artist.Artist_name
}).ToList(); <=== error happened here
}
}
}
code Behind
private List<ArtistServiceReference.Artist> ArtistDetail()
{
ArtistServiceReference.ArtistServiceClient client = new
ArtistServiceReference.ArtistServiceClient();
ArtistServiceReference.Artist[] artists = client.ArtistDetail();
return artists.ToList();
I want to move the Artist List to a DropdownList.
The error is happening in the ArtistService.cs at the end {).ToList();
Any explanation on how to fix this issue? Thanks
I based my code on this example and this example is working fine.
example code MyService.cs
public class MyService : IMyService
{
public List<Task> GetTasks()
{
using (TasksDataContext db = new TasksDataContext())
{
return (from task in db.TasksLists
select new Task()
{
Id = task.taskId,
Name = task.taskName,
}).ToList();
}
}
}
Example default.aspx.cs
private List<TaskService.Task> GetTasks()
{
TaskService.MyServiceClient client = new TaskService.MyServiceClient();
TaskService.Task[] tasks = client.GetTasks();
return tasks.ToList();
}
I don't understand why this example will work and not mine. The only difference was this example is returning to a gridview and I want to return to a dropdownlist.
Linq to Entities cannot translate the Artist object creation into SQL code (really, what is this supposed to look like?). Linq to Entities can only execute SQL queries and map returned fields to some entity to which it knows how to map (i.e. your DbSet entities). So, you need to execute the query first and then create the Artist entities locally:
public class ArtistService : IArtistService
{
public List<Artist> ArtistDetail()
{
using (ArtistDataContext db = new ArtistDataContext())
{
return (from artist in db.Artists
select new { // select only columns you need
artist.Id,
artist.Artist_name
})
.AsEnumerable() // execute query
.Select(x => new Artist { // create instance of class
Id = x.Id,
Artist_name = x.Artist_name
})
.ToList();
}
}
}
BTW it looks like you have Artist entities in your Artists DbSet. Why not simply return
return db.Artists.ToList();
I want to unit test a controller that takes a FormCollection and has the Find method. I have successfully implemented a fake DbContext and a FakeDbSet (from here) so that I can use the fake objects in my tests.
The specific method I want to test looks like this:
//
// POST: /Order/SettleOrders
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SettleOrders(FormCollection c)
{
int i = 0;
if (ModelState.IsValid)
{
var ordersCollection = new List<Order>();
// Get values of form
var OrderIdArray = c.GetValues("item.OrderId");
var UnitPriceArray = c.GetValues("item.UnitPrice");
for (i = 0; i < OrderIdArray.Count(); i++)
{
// Find order in database and update the unitprice and isconfirmed status
Order order = db.Orders.Find(Convert.ToInt32(OrderIdArray[i]));
order.UnitPrice = Convert.ToDecimal(UnitPriceArray[i]);
order.IsConfirmed = true;
db.SetModified(order);
ordersCollection.Add(order);
}
db.SaveChanges();
}
// Return orders of this date to view
var currentDate = DateTime.Today;
var orders = db.Orders.Include(o => o.Product)
.Include(o => o.User)
.Where(o => o.Date == currentDate);
return View("Confirmation", orders.ToList().OrderBy(o => o.User.Name));
}
This is how I set up the test of my OrderController using Moq:
[TestInitialize]
public void OrderControllerTestInitialize()
{
// Arrange
var unconfirmedMemoryItems = new FakeOrderSet
{
// #TODO Tests/methods should ideally not be dependent on DateTime.Today...
new Order { OrderId = 1, UnitPrice = 1.00M, Quantity = 2, Date = DateTime.Today, IsConfirmed = false },
new Order { OrderId = 2, UnitPrice = 2.00M, Quantity = 1, Date = DateTime.Today, IsConfirmed = false }
};
// Create mock unit of work
var unconfirmedMockData = new Mock<ISeashellBrawlContext>();
unconfirmedMockData.Setup(m => m.Orders).Returns(confirmedMemoryItems);
// Setup controller
unconfirmedOrderController = new OrderController(confirmedMockData.Object);
}
Then the test goes likes this to confirm the unconfirmed orders are becoming confirmed.
[TestMethod]
public void TestSettleOrdersPost()
{
// Invoke
FormCollection form = CreatesettleOrdersPostFormCollection();
var viewResult = unconfirmedOrderController.SettleOrders(form) as ViewResult;
var ordersFromView = (IEnumerable<Order>)viewResult.Model;
// Assert
Assert.AreEqual(3, ordersFromView.ElementAt(0).Quantity,
"New item should be added to older one since it has same index and is of same date");
Assert.AreEqual(true, ordersFromView.ElementAt(0).IsConfirmed,
"The item should also be set to confirmed");
}
// Helper methods
private static FormCollection CreatesettleOrdersPostFormCollection()
{
FormCollection form = new FormCollection();
form.Add("item.OrderId", "1");
form.Add("item.UnitPrice", "2.00");
form.Add("item.OrderId", "2");
form.Add("item.UnitPrice", "3.00");
return form;
}
Unfortunately I get the following error message:
Test Name: TestSettleOrdersPost
Result Message:
System.NullReferenceException: Object reference not set to an instance
of an object. Result StackTrace: at
Controllers.OrderController.SettleOrders(FormCollection c) in
Controllers\OrderController.cs:line 121
This probably has to do with the fake Find method not doing what it is supposed to do. The find method I use looks like this:
class FakeOrderSet : FakeDbSet<Order>
{
public override Order Find(params object[] keyValues)
{
var id = Convert.ToInt32(keyValues[0]);
Order o = null;
IQueryable<Order> keyQuery = this.AsQueryable<Order>();
foreach (var order in keyQuery)
{
if (order.OrderId == id)
{
o = order;
}
}
return o;
}
}
I have no idea how to improve this code. Looking at it I am convinced it should work. Since I am a 7-day noob to unit testing this conviction is of not much worth though. I hope someone can help me out.
I think you can include Find method implementation in your generic FakeDbSet<T> class.
For example if all your entites have property Id that is mapped to primary key in database you can do following:
public class FakeDbSet<T>
{
....
public T Find(params object[] keyvalues)
{
var keyProperty = typeof(T).GetProperty(
"Id",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
var result = this.SingleOrDefault(obj =>
keyProperty.GetValue(obj).ToString() == keyValues.First().ToString());
return result;
}
}
If your key property is not Id you can try to determine some algorith how to recognize key property for the entity via reflection (for example if Order class have OrderId key property you can try to determine it by getting class name with reflection and concatenating it with "Id" string).
I have the same problem:
public override TEntity Find(params object[] keyValues)
{
if (keyValues.Length == 0)
throw new ArgumentNullException("keyValues");
return this.SingleOrDefault(GenerateKeyFilter(keyValues));
}
private Expression<Func<TEntity, bool>> GenerateKeyFilter(object[] keyValues)
{
var conditions = new List<BinaryExpression>();
var objectParam = Expression.Parameter(typeof(TEntity));
var keyFields = !!!Helper.KeyFields<TEntity>();
if (keyFields.Count != keyValues.Length)
throw new KeyNotFoundException();
for (var c = 0; c < keyFields.Count; c++)
conditions.Add(Expression.MakeBinary(
ExpressionType.Equal,
Expression.MakeMemberAccess(objectParam, keyFields[c]),
Expression.Constant(keyValues[c], keyFields[c].PropertyType)
));
var result = conditions[0];
for (var n = 1; n < conditions.Count; n++)
result = Expression.And(result, conditions[n]);
return Expression.Lambda<Func<TEntity, bool>>(result, objectParam);
}
This works well, however, to create the tests I had to reconfigure the models and manually set the keys, similar to use of EntityTypeConfiguration.