lundi 22 février 2016

How do I test the number of queries that happen over time in the Entity Framework?

For some background - I'm writing an abstraction of some Entity Framework functionality to make the work of those using the Data Access Layer a little easier. I'm doing this via proxies / wrappers, and I am at the point where I'd like to test the successful use of EF's Include(). (But non of that is relevant for the specific problem here (just want to avoid people suggesting "don't test EF functionality" (I'm delegating the Include method to EF, which is what I'm actually testing)))

Ideally, I'd like to define a block (maybe via using) and have that block count the number of queries that happen within that block.

Using some psuedo-code, here is the behavior I would like:

var user = new User(id);


using(var queryCounter = new QueryCounter()){
  user.Books.SelectMany(b => b.Pages);


  Assert.Equal(2, queryCounter.NumberOfDetectedQueries);
  // the above assert would fail, due to not using the `Include` keyword.
  // as the two queries should be to select books and page ids and 
  // then to actually select the pages
}

Is there a way to achieve something like the above query counting?


UPDATE:

Thanks to @Ilya Chumakov for providing insight in to query interceptors. I've been able to get the syntax in the above example via an additional class:

public class QueryCounter : IDisposable
{
    public int Count => GlobalCounter.QueryCount;

    public QueryCounter()
    {
        GlobalCounter.QueryCount = 0;
        GlobalCounter.Active = true;
    }

    public void Dispose()
    {
        GlobalCounter.Active = false;
        GlobalCounter.QueryCount = 0; //
    }
}

and then just adding an active field to the GlobalCounter

public static class GlobalCounter
{
    public static int QueryCount = 0;
    public static bool Active = false;
}

and modifying each of the interceptor methods like so:

#if DEBUG
        if (!GlobalCounter.Active) return;
        GlobalCounter.QueryCount++;
        // or whatever output class/method works for you
        Trace.Write("Current Query Count: " + GlobalCounter.QueryCount + " -- ");
        Trace.WriteLine(command.CommandText);
#endif

Now, my tests look like this:

        using (var counter = new QueryCounter())
        {
            var pages = user.Books.First().Pages;
            Assert.Equal(1, counter.Count);
        }

Aucun commentaire:

Enregistrer un commentaire