One of the challenges I frequently encounter, is having to translate the arbitrary criteria in a testcase to LINQ selection predicates. Take the following very simple example testcase:
Feature: ModifyingInvoices In order to demonstrate the usefulness of PredicateBuilder, we will show how to verify if a C# collection contains a record that matches multiple criteria that are only known at run time Scenario: ModifyDescription When I create an invoice with number '123' for '20' euro Then The systems invoice store must look like: | Number | Amount | DescriptionPresent | Desciption | | 123 | 20 | False | | When I change the description in invoice '123' to 'Testing!' Then The systems invoice store must look like: | Number | Amount | DescriptionPresent | Description | | 123 | 20 | True | Testing! |
In this very small example, you already see that the C# code will need to determine at run-time IF an invoice exists AND MAYBE what the contents of its description should be. If an invoice has many fields. this will become exponentially complex in the code. If your criteria requires an OR construct then that’s even more complex. The solution is to use a PredicateBuilder
that builds a dynamic predicate
First install the NuGet Package LINQKit (see PredicateBuilder website) Then add the directive using LinqKit;
to your code. Now create the code that queries your data like follows:
[Then(@"The systems invoice store must look like:")] public void ThenTheSystemsInvoiceStoreMustLookLike(Table table) { var rows = table.CreateSet<InvoiceTest>(); foreach(InvoiceTest test in rows) { var MyPredicate = LinqKit.PredicateBuilder.True<Invoice>(); MyPredicate = MyPredicate.And(invoice => invoice.Number == test.Number); MyPredicate = MyPredicate.And(invoice => invoice.Amount == test.Amount); if (test.DescriptionPresent) { MyPredicate = MyPredicate.And(item => item.Desciption.Equals(test.Description)); } //Test that our datastore contains an invoice that matches the predicate from the testcase IQueryable<Invoice> Matches = this.Invoices.AsQueryable().Where<Invoice>(MyPredicate); Assert.AreEqual(1, Matches.Count()); } }