Search code examples
ravendbnancy

RavenDB : How do I use the RavenProfiler in my UnitTests?


I am using NancyFX + RavenDB. I am currently trying to implement the Ayende recommended Denormalized Reference technique to build Domain references out from an AggregateRoot. If you read that link you can see that the trick is to load the parent instance and then pre-fetch the referenced instances using RavenDB's 'Include' statement.

I have done all this and it appears to work but I am struggling to determine, via a unit-test, whether the referenced instances really are pre-fetched. Here is a snippet from my unit-test to illustrate:

[Fact]
public void Should_preload_the_mentor_mentee_references_to_improve_performance()
{
    //Given
    var db = Fake.Db();
    var mentor = Fake.Mentor(db);
    var mentee = Fake.Mentee(db);
    var relationship = Fake.Relationship(mentor, mentee, db);

    //When
    relationship = db
        .Include("Mentor.Id")
        .Include("Mentee.Id")
        .Load<Relationship>(relationship.Id);
    mentor = db.Load<User>(relationship.Mentor.Id);
    mentee = db.Load<User>(relationship.Mentee.Id);

    //Then
    relationship.ShouldNotBe(null);
    mentor.ShouldNotBe(null);
    mentee.ShouldNotBe(null);
}

The unit test above checks that I can load my instances from my fake db (its an in-memory, embedded instance of RavenDB) but it does not check whether they are pre-fetched.

I thought that perhaps I could use the RavenProfiler. Maybe this would count the number of db requests which I could then assert against (the unit-test above would fail if requests > 1 for example).

To make this work I had to install the MVCIntegration package to my unit-test project (ouch)

PM> install-package RavenDB.Client.MvcIntegration

I also had to add a reference to System.Web, which made me shiver. I don't think this is going to work.

I then added the appropriate initialisation to my Fake db provider, like this:

public class InMemoryRavenSessionProvider : IRavenSessionProvider
{
    private static IDocumentStore documentStore;

    public static IDocumentStore DocumentStore { get { return (documentStore ?? (documentStore = CreateDocumentStore())); } }

    private static IDocumentStore CreateDocumentStore()
    {
        var store = new EmbeddableDocumentStore { RunInMemory = true};
        store.Initialize();
        store.Conventions.IdentityPartsSeparator = "-";
        RavenProfiler.InitializeFor(store); //<-- Here is the Profiler line
        return store;
    }

    public IDocumentSession GetSession()
    {
        return DocumentStore.OpenSession();
    }
}

Finally I tried to retrieve a value of some sort from the RavenProfiler at the end of my unit-test:

var requests = RavenProfiler.CurrentRequestSessions();

This did not work! It failed inside the RavenProfiler because the HttpContext was null - which was what my premonition about the System.Web must have been about. Oh well.

So, how do I count the number of requests made to my RavenDB instance? And can this be done without requiring MVC or System.Web so it can easily be bolted into unit-tests?

Thanks


Solution

  • You can use the following code for this:

    session.Advanced.NumberOfRequests
    

    The RavenDB profiler won't run against an embedded document store.

    Also you can take a look at the unit tests in the Raven source, they test this scenario.