2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Swift】Realmのモックを作成する

Posted at

はじめに

昨日、Realmを使ってみたという記事を書きました。
それに関連してRealmのテストを書く際にMockを読み込む場面があったので記録しておきます。

必要ツール

事前準備

RealmEntity
public class RealmEntity: Object {
    @Persisted(primaryKey: true) public var id: Int = 0
}
RealmRepositoryProtocol
public protocol RealmRepositoryProtocol {
    func get() -> Results<RealmEntity>
    func add(_ bookmark: RealmEntity) throws
    func delete(_ bookmark: RealmEntity) throws
}

public final class RealmRepository: RealmRepositoryProtocol {
    let realm: Realm
    
    public init(realm: Realm = try! Realm()) {
        self.realm = realm
    }
    
    public func get() -> Results<RealmEntity> {
        realm.objects(RealmEntity.self)
    }
    
    public func add(_ bookmark: RealmEntity) throws {
        try realm.write {
            realm.add(bookmark)
        }
    }
    
    public func delete(_ bookmark: RealmEntity) throws {
        guard let bookmark = realm.object(ofType: RealmEntity.self, forPrimaryKey: bookmark.id) else {
            throw NSError(domain: "primary key not found", code: 0)
        }
        try realm.write {
            realm.delete(bookmark)
        }
    }
}

やりかた

① Realmオブジェクトを保存する

ContentView
import SwiftUI

struct ContentView: View {
    private let repository = RealmRepository()
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .padding()
        .onAppear {
            let realmEntity = RealmEntity()
            realmEntity.id = 100
            try? repository.add(realmEntity)
        }
    }
}

② 保存されてるファイルを取得する

ContentView
import SwiftUI
import RealmSwift

struct ContentView: View {
    private let repository = RealmRepository()
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .padding()
        .onAppear {
//            let realmEntity = RealmEntity()
//            realmEntity.id = 100
//            try? repository.add(realmEntity)
            
            print(Realm.Configuration.defaultConfiguration.fileURL!)
            // ↓ これが出力された ↓
            // file:///Users/miyamototaishin/Library/Developer/CoreSimulator/Devices/737336AC-3C03-4CD2-BC16-EAC4B1559152/data/Containers/Data/Application/0A92DBCD-5B9A-4F56-98E8-5E14390F3E18/Documents/default.realm
        }
    }
}

③ 保存されてるファイルを保存する

ターミナル
open file:///Users/miyamototaishin/Library/Developer/CoreSimulator/Devices/737336AC-3C03-4CD2-BC16-EAC4B1559152/data/Containers/Data/Application/AE835C93-B793-4B0F-9C9D-7179C2BB5A04/Documents/default.realm

以下のように先ほど保存した100があるのがわかる
スクリーンショット 2023-04-16 22.25.01.png

「Local Realm」を選択して書き出します。
スクリーンショット 2023-04-16 22.26.16 1.png

④ 保存したファイルをXcodeに取り込む

スクリーンショット 2023-04-16 22.28.10.png

スクリーンショット 2023-04-16 22.29.25.png

④ RepositoryMockを作成する

RealmRepositoryMock
public final class RealmRepositoryMock: RealmRepositoryProtocol {
    var realm: Realm {
        let url = URL(fileURLWithPath: Bundle.main.path(forResource: "default", ofType: "realm")!)
        return try! Realm(configuration: Realm.Configuration(fileURL: url, schemaVersion: 4))
    }
    
    public func get() -> Results<RealmEntity> {
        realm.objects(RealmEntity.self)
    }
    
    public func add(_ bookmark: RealmEntity) throws {}
    
    public func delete(_ bookmark: RealmEntity) throws {}
}

⑤ ビルドとプレビューでわける

ContentView
import SwiftUI
import RealmSwift

struct ContentView: View {
    @State var items: [RealmEntity] = []
    
    let repository: RealmRepositoryProtocol
    
    var body: some View {
        List(items, id: \.id) { item in
            Text(item.id.description)
        }
        .onAppear {
            // 起動時にランダムで数値を保存
            let realmEntity = RealmEntity()
            realmEntity.id = Int.random(in: 0...100)
            try? repository.add(realmEntity)
            // 保存されたものを取得
            items = Array(repository.get())
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(repository: RealmRepositoryMock())
    }
}

おわり

シュミレーターの方は起動するたびに数値が増えていきます。
プレビューの方は何回起動しても増えません。

シュミレーター プレビュー
Simulator Screen Shot - iPhone 14 Pro - 2023-04-16 at 22.44.38.png スクリーンショット 2023-04-16 22.44.34.png

参考記事

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?