【发布时间】:2012-04-25 13:29:06
【问题描述】:
在使用 RavenDb 进行单元测试时,通常会检索或以其他方式处理新添加的数据。这可能导致“过时索引”异常,例如
Bulk operation cancelled because the index is stale and allowStale is false
根据一些答案
- How should stale indexes be handled during testing?
- WaitForNonStaleResults per DocumentStore
- RavenDb : Update a Denormalized Reference property value
在处理查询或批处理操作之前强制数据库(IDocumentStore 实例)等到其索引不陈旧的方法是在IDocumentStore 初始化期间使用DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites,如下所示:
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();
}
}
很遗憾,上面的代码不起作用。我仍然收到有关过时索引的例外情况。这些可以通过放入包含.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite()) 的虚拟查询来解决。
这很好,只要这些可以包含在单元测试中,但是如果它们不能包含呢?我发现这些 WaitForNonStaleResults* 调用正在悄悄进入生产代码,这样我就可以让单元测试通过。
那么,有没有一种可靠的方法,使用最新版本的 RavenDb,在允许处理命令之前强制索引更新 - 仅用于单元测试的目的?
编辑 1
这是基于下面给出的答案的解决方案,该解决方案强制等待索引不陈旧。为了单元测试的方便,我把它写成一个扩展方法;
public static class IDocumentSessionExt
{
public static void ClearStaleIndexes(this IDocumentSession db)
{
while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
}
}
这是一个单元测试,它使用了详细的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);
}
}
【问题讨论】:
-
这现在是针对 DocumentStore 而不是 DocumentSession,因此扩展方法将更改为使用 db.Advanced.DocumentStore.DatabaseCommands.GetStatistics().StaleIndexes.Any() 之类的东西,或者只是如果可以的话,直接交出 DocumentStore
标签: unit-testing ravendb