Question

I normally mock IDocumentSession in my MSpec with Machine.Fakes, which the RavenDB guys don't like. How do I use the EmbeddableDocumentStore with Machine.Fakes ?

Was it helpful?

Solution

gist: https://gist.github.com/JasonMore/5345697

Hooking RavenDB InMemory to Machine.Fakes

public class RavenInMemorySlowRunner
{
    public class NoStaleQueriesAllowed : IDocumentQueryListener
    {
        public void BeforeQueryExecuted(IDocumentQueryCustomization queryCustomization)
        {
            queryCustomization.WaitForNonStaleResults();
        }
    }

    public class AllDocumentsById : AbstractIndexCreationTask
    {
        public override IndexDefinition CreateIndexDefinition()
        {
            return new IndexDefinition
            {
                Name = "AllDocumentsById",
                Map = "from doc in docs let DocId = doc[\"@metadata\"][\"@id\"] select new {DocId};"
            };
        }
    }

    public static EmbeddableDocumentStore Store { get; set; }
    public static IDocumentSession Session { get; set; }

    OnEstablish context = fakeAccessor =>
    {
        fakeAccessor.Configure(x => x.For<IDocumentSession>().Use(() =>
        {
            if (Store == null)
            {
                Store = new EmbeddableDocumentStore { RunInMemory = true };
                Store.RegisterListener(new NoStaleQueriesAllowed());
                Store.Initialize();

                // RegisterServicesWithNinject is in the project where the indexes live
                IndexCreation.CreateIndexes(typeof(RegisterServicesWithNinject).Assembly, Store);
                IndexCreation.CreateIndexes(typeof(RavenInMemorySlowRunner).Assembly, Store);
            }

            if (Session == null)
            {
                Session = Store.OpenSession();
            }

            return Session;
        }));

    };

    OnCleanup subject = subject =>
    {
        Session.Advanced.DocumentStore.DatabaseCommands.DeleteByIndex("AllDocumentsById", new IndexQuery());
        Session.SaveChanges();
        Session.Dispose();
    };
}

The Test

public class CurrentSiteModelServiceSpecs : WithSubject<CurrentSiteModelService>
{
    Establish that = () =>
    {
        // use the raven in memory runner since 
        // we are using lots of raven magic in this service
        With(new RavenInMemorySlowRunner());
    };
}

/// <summary>
/// Determine Site Model for Dev
/// </summary>
public class When_Determining_SiteModel_for_dev : CurrentSiteModelServiceSpecs
{
    public static SiteViewModel _siteViewModelResult;
    public static IHttpCookie _cookie;

    Because of = () =>
        _siteViewModelResult = Subject.DetermineSiteModelForDevEnvironment();
}

public class And_Cookie_not_set : When_Determining_SiteModel_for_dev
{
    It returns_null = () =>
        _siteViewModelResult.ShouldBeNull();
}

public class And_Cookie_set : When_Determining_SiteModel_for_dev
{

    Establish that = () =>
    {
        _cookie = An<IHttpCookie>();
        _cookie.Value = "site/123";

        The<ICookieService>()
            .WhenToldTo(x => x.GetCookie(".CMS3DevSite"))
            .Return(_cookie);

        var site1 =  new SiteModel{ Id = "site/123", HostName = "foo" };
        var site2 =  new SiteModel{ Id = "site/456", HostName = "bar" };

        The<IDocumentSession>().Store(site1);
        The<IDocumentSession>().Store(site2);
        The<IDocumentSession>().SaveChanges();

    };

    It loads_site = () =>
        _siteViewModelResult.HostName.ShouldEqual("foo");
}

public class And_Cookie_set_but_site_does_not_exist : When_Determining_SiteModel_for_dev
{
    Establish that = () =>
    {
        _cookie = An<IHttpCookie>();
        _cookie.Value = "site/123";

        The<ICookieService>()
            .WhenToldTo(x => x.GetCookie(".CMS3DevSite"))
            .Return(_cookie);
    };

    It returns_null = () =>
        _siteViewModelResult.ShouldBeNull();
}

The Service I'm testing

public interface ICurrentSiteModelService { RedirectToResult SetSiteModel(string path, Uri url); }

public class CurrentSiteModelService : ICurrentSiteModelService
{
    readonly IDocumentSession _documentSession;
    readonly ICookieService _cookieService;

    public CurrentSiteModelService(
        IDocumentSession documentSession,
        ICookieService cookieService)
    {
        _documentSession = documentSession;
        _cookieService = cookieService;
    }


// cruft removed here

    // load site in dev mode based on cookie.
    internal SiteViewModel DetermineSiteModelForDevEnvironment()
    {
        var cookie = _cookieService.GetCookie(".CMS3DevSite");
        if (cookie != null && !String.IsNullOrEmpty(cookie.Value))
        {
            SiteViewModel site = _documentSession.
                Query<SiteViewModel, SiteViewIndex>()
                .Where(s => s.Id == cookie.Value)
                .AsProjection<SiteViewModel>()
                .FirstOrDefault();

            if (site != null)
            {
                return site;
            }
        }

        return null;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top