Cuando se prueban las unidades con RavenDb, a menudo ocurre que datos recién agregados se recuperan o procesan. Esto puede llevar a excepciones de "índice obsoleto", p.RavenDb: Fuerza los índices a esperar hasta que no estén obsoletos mientras se prueban las unidades
Bulk operation cancelled because the index is stale and allowStale is false
De acuerdo con una serie de respuestas
- How should stale indexes be handled during testing?
- WaitForNonStaleResults per DocumentStore
- RavenDb : Update a Denormalized Reference property value
La forma de obligar a la base de datos (la IDocumentStore
ejemplo) para esperar hasta que sus índices no estan rancios antes del procesamiento una operación de consulta o lote es utilizar DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites
durante la inicialización IDocumentStore
, así:
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();
}
}
Por desgracia, el código anterior no funciona. Todavía recibo excepciones con respecto a los índices obsoletos. Estos pueden resolverse mediante consultas ficticias que incluyen .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.
Esto está bien, siempre que estos puedan estar contenidos en la Prueba de Unidad, pero ¿qué pasa si no pueden? Estoy descubriendo que estas llamadas WaitForNonStaleResults*
están entrando sigilosamente en el código de producción solo para poder pasar las pruebas unitarias.
Entonces, ¿hay una forma segura de utilizar la última versión de RavenDb para forzar el refrescamiento de los índices antes de permitir que se procesen los comandos, solo para fines de prueba unitaria?
Editar 1
Aquí es una solución basada en la respuesta dar a continuación que obliga a esperar hasta que el índice no está demasiado cargado. Lo he escrito como un método de extensión por el bien de la conveniencia de las pruebas unitarias;
public static class IDocumentSessionExt
{
public static void ClearStaleIndexes(this IDocumentSession db)
{
while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
}
}
Y aquí es una prueba de unidad que estaba utilizando la técnica de WaitForNonStaleResultsAsOfLastWrite
prolijo pero ahora utiliza el método de extensión más ordenado.
[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);
}
}
Esto ahora se lleva a cabo contra el DocumentStore en lugar de la DocumentSession, por lo que el método de extensión cambiaría a usar algo como db.Advanced.DocumentStore.DatabaseCommands. GetStatistics(). StaleIndexes.Any(), o simplemente entregue el DocumentStore directamente si puede – adrian