unit-testing ravendb

unit testing - RavenDb: obliga a los índices a esperar hasta que no estén obsoletos mientras se prueba la unidad



unit-testing (3)

En realidad, puede agregar un servicio de escucha de consultas en el Almacén de documentos para esperar los resultados que no sean de fase. Esto se puede usar solo para pruebas unitarias, ya que está en el almacén de documentos y no en cada operación.

// Initialise the Store. var documentStore = new EmbeddableDocumentStore { RunInMemory = true }; documentStore.Initialize(); // Force queries to wait for indexes to catch up. Unit Testing only :P documentStore.RegisterListener(new NoStaleQueriesListener()); .... #region Nested type: NoStaleQueriesListener public class NoStaleQueriesListener : IDocumentQueryListener { #region Implementation of IDocumentQueryListener public void BeforeQueryExecuted(IDocumentQueryCustomization queryCustomization) { queryCustomization.WaitForNonStaleResults(); } #endregion } #endregion

(Robado descaradamente de RavenDB, ¿cómo descargar? )

Cuando la unidad prueba con RavenDb, a menudo ocurre que los datos recién agregados se recuperan o se procesan de otra manera. Esto puede llevar a excepciones de ''índice obsoleto'' por ejemplo

Bulk operation cancelled because the index is stale and allowStale is false

Según varias respuestas.

La forma de forzar a la base de datos (la instancia de IDocumentStore ) a esperar hasta que sus índices no estén obsoletos antes de procesar una consulta o operación por lotes es usar DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites durante la inicialización de IDocumentStore , como esto:

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, Conventions = new DocumentConvention { DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites, IdentityPartsSeparator = "-" } }; store.Initialize(); IndexCreation.CreateIndexes(typeof (RavenIndexes).Assembly, store); return store; } public IDocumentSession GetSession() { return DocumentStore.OpenSession(); } }

Desafortunadamente, el código anterior no funciona. Todavía estoy recibiendo excepciones con respecto a los índices obsoletos. Estos se pueden resolver al colocar consultas ficticias que incluyen .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite()) .

Esto está bien, siempre y cuando estos puedan estar contenidos en la prueba de unidad, pero ¿y si no pueden? Estoy encontrando que estas llamadas WaitForNonStaleResults* se están introduciendo en el código de producción solo para que pueda pasar las pruebas unitarias.

Entonces, ¿existe una forma segura de usar la última versión de RavenDb para forzar la actualización de los índices antes de permitir que se procesen los comandos, solo para fines de prueba unitaria?

Editar 1

Aquí hay una solución basada en la respuesta que figura a continuación que obliga a esperar hasta que el índice no esté obsoleto. Lo he escrito como un método de extensión por conveniencia de prueba de unidad;

public static class IDocumentSessionExt { public static void ClearStaleIndexes(this IDocumentSession db) { while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0) { Thread.Sleep(10); } } }

Y aquí hay una prueba de unidad que usaba la técnica WaitForNonStaleResultsAsOfLastWrite pero ahora usa el método de extensión WaitForNonStaleResultsAsOfLastWrite .

[Fact] public void Should_return_list_of_Relationships_for_given_mentor() { using (var db = Fake.Db()) { var mentorId = Fake.Mentor(db).Id; Fake.Relationship(db, mentorId, Fake.Mentee(db).Id); Fake.Relationship(db, mentorId, Fake.Mentee(db).Id); Fake.Relationship(db, Fake.Mentor(db).Id, Fake.Mentee(db).Id); //db.Query<Relationship>() // .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite()) // .Count() // .ShouldBe(3); db.ClearStaleIndexes(); db.Query<Relationship>().Count().ShouldBe(3); MentorService.GetRelationships(db, mentorId).Count.ShouldBe(2); } }


Si tiene un índice Map / Reduce, DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites no funcionará. Necesitas usar un método alternativo.

En tus pruebas de unidades, llama a un código como este, justo después de que hayas insertado cualquier información, esto forzará a todos los índices a actualizarse antes de hacer cualquier otra cosa:

while (documentStore.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0) { Thread.Sleep(10); }

Actualización Por supuesto, puede ponerlo en un método de extensión si desea:

public static class IDocumentSessionExt { public static void ClearStaleIndexes(this IDocumentSession db) { while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0) { Thread.Sleep(10); } } }

Entonces puedes decir:

db.ClearStaleIndexes();


Tenga en cuenta que los índices StaleIndexes también incluyen índices anónimos y deshabilitados, que nunca se actualizarán.

Entonces, para evitar esperar, use esta propiedad indefinidamente en su lugar:

var staleIndices = store.DatabaseCommands.GetStatistics().CountOfStaleIndexesExcludingDisabledAndAbandoned;