bio*_*tal 24 unit-testing ravendb
使用RavenDb进行单元测试时,通常会检索或以其他方式处理新添加的数据.这可能导致"陈旧索引"例外,例如
Bulk operation cancelled because the index is stale and allowStale is false
Run Code Online (Sandbox Code Playgroud)
根据一些答案
强制数据库(IDocumentStore实例)在处理查询或批处理操作之前等待其索引未过时的方法是DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites在IDocumentStore初始化期间使用,如下所示:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,上面的代码不起作用.我仍然收到有关陈旧索引的例外情况.这些可以通过放入包含的虚拟查询来解决.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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个使用详细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);
}
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*ren 29
如果您有Map/Reduce索引,DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites则无效.您需要使用替代方法.
在你的单元测试中,在你插入任何数据之后直接调用这样的代码,这将强制所有索引在你做其他事情之前更新:
while (documentStore.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
Run Code Online (Sandbox Code Playgroud)
更新您当然可以将其放在扩展方法中,如果您想:
public static class IDocumentSessionExt
{
public static void ClearStaleIndexes(this IDocumentSession db)
{
while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以说:
db.ClearStaleIndexes();
Run Code Online (Sandbox Code Playgroud)
Ran*_*ric 14
您实际上可以在DocumentStore上添加查询侦听器以等待非陈旧结果.这可以仅用于单元测试,因为它在文档存储上而不是每个操作.
// 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4419 次 |
| 最近记录: |