Realm 使用Entwine测试基于领域的发布服务器时出现意外行为
我正在修补一个应用程序的持久性中间件,该应用程序使用了类似Redux的体系结构,使用Realm作为后端。数据库查询的结果应由联合发布服务器发出 尽管Realm现在支持Combine并提供FrozenCollection类型来管理线程和并发相关的错误,但有人建议我使用DTO(结构)使事情尽可能可预测。我已经编写了一个测试,它使用Entwine来确保将Realm FrozenCollection转换为DTO的行为符合预期,但是TestableSubscriber在时间索引0接收到一个空数组,而实际上它应该接收三个输入(t=0时的初始空数组,t=100时的测试集为3个元素,t=200时的第二个测试集为3个元素) 我已经恢复到使用预期进行测试,以及使用print()调试发布服务器,并获得预期的输出(总共发出6个元素,转换为DTO正常工作),因此我假设我做错了什么,尽管我猜可能存在外部错误 目前正在使用Xcode12、iOS14。代码如下: 中间件(SUT) <代码>导入基础 进口联合收割机 导入RealmSwift 最终类持久化中间件{ private var cancelables=Set 2020-10-03 15:49:39.231129+0100 SwiftRex ToDo持续存在[14502:643297]设置 2020-10-03 15:49:39.232989+0100 SwiftRex ToDo持续[14502:643297]拆除 测试用例“-[SwiftRex_ToDo_PersistedTests.SwiftRex_ToDo_PersistedTests TestCorrectNumberOfObjectsStoredRealm]”已通过(0.067秒)。 测试用例“-[SwiftRex_ToDo_PersistedTests.SwiftRex_ToDo_PersistedTests Tests MiddlewarePublisherUsingEntWine]”已启动。 2020-10-03 15:49:39.262702+0100 SwiftRex ToDo持续存在[14502:643297]设置 2020-10-03 15:49:39.264956+0100 SwiftRex ToDo持久化[14502:643474][]nw_协议获取图像块调用dlopen libquic失败 TestSequence(内容:[(0,.subscribe),(0,.input([]))] 脱硝 2020-10-03 15:49:39.267422+0100 SwiftRex ToDo持续[14502:643297]拆除 测试用例“-[SwiftRex_ToDo_PersistedTests.SwiftRex_ToDo_PersistedTests Tests MiddlewarePublisherUsingEntWine]”通过(0.033秒)。 测试用例“-[SwiftRex_ToDo_PersistedTests.SwiftRex_ToDo_PersistedTests Tests MiddlewarePublisherUsingExpection]”已启动。 2020-10-03 15:49:39.272248+0100 SwiftRex ToDo持续存在[14502:643297]设置 [14502:643297][SwiftRex_ToDo________________________________________________________________________________________________(id:4,名称:“烹饪晚餐”),SwiftRex_ToDo_.ToDo.DTO(id:5,名称:“支付账单”)] 脱硝 2020-10-03 15:49:39.275235+0100 SwiftRex ToDo持续[14502:643297]拆除 测试用例“-[SwiftRex_ToDo_PersistedTests.SwiftRex_ToDo_PersistedTests TestMiddleWarePublisherUsingExpection]”已通过(0.008秒)。 测试套件“SwiftRex_ToDo_PersistedTests”于2020-10-03 15:49:39.277通过。 在0.108(0.109)秒内执行了3次测试,0次失败(0次意外) 测试套件“SwiftRex ToDo PersistedTests.xTest”于2020-10-03 15:49:39.277通过。 在0.108(0.110)秒内执行了3次测试,0次失败(0次意外) 测试套件“所有测试”于2020-10-03 15:49:39.292通过。Realm 使用Entwine测试基于领域的发布服务器时出现意外行为,realm,swift5,xctest,combine,Realm,Swift5,Xctest,Combine,我正在修补一个应用程序的持久性中间件,该应用程序使用了类似Redux的体系结构,使用Realm作为后端。数据库查询的结果应由联合发布服务器发出 尽管Realm现在支持Combine并提供FrozenCollection类型来管理线程和并发相关的错误,但有人建议我使用DTO(结构)使事情尽可能可预测。我已经编写了一个测试,它使用Entwine来确保将Realm FrozenCollection转换为DTO的行为符合预期,但是TestableSubscriber在时间索引0接收到一个空数组,而实际上
执行了3个测试,在0.108(0.126)秒内0次失败(0次意外)我在使用EntwineTest测试CoreData Combine包装器时遇到了类似的问题。我注意到在您的方法
func allToDos(…){…}
中将调度程序设置为.receive(on:DispatchQueue.main)
我可以想象这是一个问题,因为Entwine的TestScheduler
不是线程安全的:
import Foundation
import Combine
import RealmSwift
final class PersistenceMiddleware {
private var cancellables = Set<AnyCancellable>()
private var subject = CurrentValueSubject<[ToDo.DTO], Never>([])
func allToDos(in realm: Realm = try! Realm()) -> AnyPublisher<[ToDo.DTO], Never> {
realm.objects(ToDo.self)
.collectionPublisher
// .print()
.assertNoFailure()
.freeze()
.map { item in
item.map { $0.convertToDTO() }
}
// .print()
.receive(on: DispatchQueue.main)
.subscribe(subject)
.store(in: &cancellables)
return subject.eraseToAnyPublisher()
}
deinit {
print("Deinit")
cancellables = []
}
}
import XCTest
import Combine
import RealmSwift
import EntwineTest
@testable import SwiftRex_ToDo_Persisted
class SwiftRex_ToDo_PersistedTests: XCTestCase {
private var realm: Realm?
private var testSet1: [ToDo] {
[
ToDo(name: "Mow lawn"),
ToDo(name: "Wash car"),
ToDo(name: "Clean windows")
]
}
private var testSet2: [ToDo] {
[
ToDo(name: "Walk dog"),
ToDo(name: "Cook dinner"),
ToDo(name: "Pay bills")
]
}
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
realm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: UUID().uuidString))
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
realm = nil
}
func testCorrectNumberOfObjectsStoredInRealm() {
realm!.addForTesting(objects: testSet1)
XCTAssertEqual(realm!.objects(ToDo.self).count, 3)
realm!.addForTesting(objects: testSet2)
XCTAssertEqual(realm!.objects(ToDo.self).count, 6)
}
func testMiddlewarePublisherUsingEntwine() {
let middleware = PersistenceMiddleware()
let scheduler = TestScheduler()
let subscriber = scheduler.createTestableSubscriber([ToDo.DTO].self, Never.self)
middleware.allToDos(in: self.realm!)
.subscribe(subscriber)
scheduler.schedule(after: 100) { self.realm!.addForTesting(objects: self.testSet1) }
scheduler.schedule(after: 200) { self.realm!.addForTesting(objects: self.testSet2) }
scheduler.resume()
print("\(subscriber.recordedOutput)")
}
func testMiddlewarePublisherUsingExpectation() {
let middleware = PersistenceMiddleware()
var cancellables = Set<AnyCancellable>()
let receivedValues = expectation(description: "received expected number of published objects")
middleware.allToDos(in: realm!)
.sink { result in
if result.count == 6 {
NSLog(result.debugDescription)
receivedValues.fulfill()
}
}
.store(in: &cancellables)
realm!.addForTesting(objects: testSet1)
realm!.addForTesting(objects: testSet2)
waitForExpectations(timeout: 1, handler: nil)
}
}