领域不适用于xUnite和.net核心

时间:2019-04-06 14:46:18

标签: .net-core realm xunit

我在使用xUnite和Net core运行领域时遇到问题。这是我要运行的非常简单的测试

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());
        }
    }

我在尝试使用InMemoryConfiguration创建Realm实例的不同计算机(Windows和Mac)上遇到了不同的异常。 在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

我正在使用Realm 3.3.0和xUnit 2.4.1 我曾尝试将其降级为Realm 2.2.0,但也无法正常工作。

1 个答案:

答案 0 :(得分:0)

此问题的解决方案在this 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;
}

尽管我花了一些时间将其应用于我的解决方案。 首先,我正在使用Nito.AsyncEx.AsyncContext,而不仅仅是将上下文设置为null。因为否则自动更改将不会通过线程传播,因为领域需要非空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;
        }
    }

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

  

如果您设置了SynchronisationContext.Current没问题,但是   这将导致WriteAsync再次在线程池上分派   可能会创建另一个工作线程。因此,如果您在自己的计算机中使用Current   线程,请考虑仅调用Write而不是WriteAsync

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