Realm 不适用于 xUnite 和 .net core



我在使用 xUnite 和 Net core 运行 realm 时遇到问题。这是一个非常简单的测试,我想运行

public class UnitTest1
{
[Scenario]
public void Test1()
{
var realm = Realm.GetInstance(new InMemoryConfiguration("Test123"));
realm.Write(() =>
{
realm.Add(new Product());
});
var test = realm.All<Product>().First();
realm.Write(() => realm.RemoveAll());
}
}

我在不同的机器(Windows和Mac)上得到不同的异常,我尝试使用InMemoryConfiguration创建一个Realm instace。 在Mac上,我收到以下异常

libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.

在 Windows 上,我在运行时出现以下异常

ERROR Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. at 
System.Net.Sockets.NetworkStream.Read(Span1 destination) at 
System.Net.Sockets.NetworkStream.ReadByte() at 
System.IO.BinaryReader.ReadByte() at 
System.IO.BinaryReader.Read7BitEncodedInt() at 
System.IO.BinaryReader.ReadString() at 
Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.LengthPrefixCommunicationChannel.NotifyDataAvailable() at 
Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.TcpClientExtensions.MessageLoopAsync(TcpClient client, ICommunicationChannel channel, Action1 errorHandler, CancellationToken cancellationToken) Source: System.Net.Sockets HResult: -2146232800 Inner Exception: An existing connection was forcibly closed by the remote host HResult: -2147467259

我正在使用领域 3.3.0 和 xUnit 2.4.1 我尝试降级到 Realm 2.2.0,但它也没有奏效。

这个问题的解决方案在这个Github帖子中找到

了这段代码帮助我解决了这个问题

Realm GetInstanceWithoutCapturingContext(RealmConfiguration config)
{
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
Realm realm = null;
try
{
realm = Realm.GetInstance(config);
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
return realm;
}

尽管我花了一段时间才将其应用于我的解决方案。 首先,我不只是将上下文设置为null,而是使用Nito.AsyncEx.AsyncContext。因为否则自动更改将不会通过线程传播,因为 Realm 需要一个非空SynchronizationContext才能使该功能正常工作。所以,在我的例子中,该方法看起来像这样

public class MockRealmFactory : IRealmFactory
{
private readonly SynchronizationContext _synchronizationContext;
private readonly string _defaultDatabaseId;
public MockRealmFactory()
{
_synchronizationContext = new AsyncContext().SynchronizationContext;
_defaultDatabaseId = Guid.NewGuid().ToString();
}
public Realm GetRealmWithPath(string realmDbPath)
{
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
Realm realm;
try
{
realm = Realm.GetInstance(new InMemoryConfiguration(realmDbPath));
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
return realm;
}
}

此外,这修复了许多失败的单元测试。但我仍然收到同样的异常 - 从不正确的线程访问 Realm。我不知道为什么,因为一切都设置正确。然后我发现失败的测试与我使用异步领域 API 的方法有关,尤其是realm.WriteAsync.经过更多的挖掘,我在领域文档中发现了以下几行。

如果您设置了SynchronisationContext.Current,这不是问题,但是 这将导致 WriteAsync 在线程池上再次调度,这 可能会创建另一个工作线程。因此,Current如果您在您的 线程,请考虑只调用Write而不是WriteAsync

在我的代码中,没有直接需要使用异步 API。我删除并替换为同步Write,所有测试再次变为绿色!我想如果我发现自己因为某种批量插入而需要使用异步 API,我要么模拟该特定 API,要么使用Task.Run而不是使用 Realm 的版本替换我自己的后台线程。

最新更新