본문 바로가기

swift공부

[RealmSwift Test] "오운완" Mock을 활용한 Realm 테스트

반응형

여러번 수정해서 나온 설계.. 또 수정해야할지도........

요즘 테스트 공부를 한창 하고 있다. 

realm를 테스트할 때 실제 realm객체에 접근하고자 하면 테스트 간 일관성이 유지되지 않는다고 한다.

(음..실제로 가짜 객체를 두지 않고 테스트 코드를 돌려봤을 때 RealmStudio에는 사실 반영이 되지 않았다. 그치만 또 이미 있는 데이터라고 나타나서 테스트도 되지 않았다.. 영향을 주는 것 같기도 주지 않는 것 같기도..더 알아볼 필요가 있을 것 같다.)

 

그래서 테스트용 가짜 객체를 만드는데 이것을 "Mock"이라고 한다.

실제 서비스에는 ProductionRealm, 테스트에는 MockRealm 이렇게 구분했다. 

 

우선 프로토콜을 사용해서 RealmProvider(어떤 Realm을 제공해줄지)

protocol RealmProviderProtocol {
    func makeRealm() throws -> Realm
}

그리고 프로토콜을 받아서 실제 서비스용 realm인지 테스트용 realm인지 구분시켰다. 

class ProductionRealmProvider: RealmProviderProtocol {
    func makeRealm() throws -> Realm {
        return try Realm()
    }
}

class MockRealmProvider: RealmProviderProtocol {
    func makeRealm() throws -> Realm {
        return try Realm(configuration: Realm.Configuration(inMemoryIdentifier: "testRealm"))
    }
}

 

 

그리고 실제로 사용하는 ViewModel에서는 ProductionRealmProvider를 주입시켜주었고

    private var viewModel = RegisterMyBodyInfoViewModel(realmProvider: ProductionRealmProvider())

테스트코드 부분에서는 MockRealmProvider를 주입시켰다. 

final class BodyInputDataValidatorTest: XCTestCase {

    var sut: BodyInfoDataManager!
    var realmProvider: MockRealmProvider!
    var testRealm: Realm!
    
    override func setUp() {
        realmProvider = MockRealmProvider()
        testRealm = try! realmProvider.makeRealm()
        let realmManager = RealmManager(realm: testRealm)
        sut = BodyInfoDataManager(realmManager: realmManager)
    }


BodyInputDataValidatorTest 파일은 Realm 데이터 중 BodyInputDataManager에 있는 메서드들을 테스트 하는 파일이다.
BodyInputDataManager에는 '생성', '읽기', '수정'의 기능이 있고 이를 테스트 해보고자 하였다. 

 

 

여기서부턴 내 뇌피셜이 많이 들어가있기 때문에 틀린 Unit Test일수도 있으니 감안해서 보기..! (틀림 뭐 어때 일단 하는거지)

 

 

읽기 메서드를 테스트 하기 위해서는 우선 데이터가 생성되어 있어야 한다. 때문에 setUp() 메서드 안에 
데이터를 먼저 생성해주었다. 

    override func setUp() {
        realmProvider = MockRealmProvider()
        testRealm = try! realmProvider.makeRealm()
        let realmManager = RealmManager(realm: testRealm)
        sut = BodyInfoDataManager(realmManager: realmManager)
        sut.createBodyInfoData(weight: ExpectedBodyInfoData.weight,
                               skeletalMusleMass: ExpectedBodyInfoData.skeletalMusleMass,
                               fatPercentage: ExpectedBodyInfoData.fatPercentage,
                               date: ExpectedBodyInfoData.date,
                               id: ExpectedBodyInfoData.id)
    }

 

여기서 나는 한가지 이슈를 맞이하는데 나 때매 발생한 "휴먼 에러"이다. 오타로 인해..

테스트는 의도한 바를 테스트해야할 필요가 있어서 "휴먼 에러"가 있으면 안된다고 생각해서 따로 테스트용 구조를 만들어 주었다. 

struct ExpectedBodyInfoData {
    static let weight: Double = 83
    static let skeletalMusleMass: Double = 40
    static let fatPercentage: Double = 17
    static let date: String = "2023.09.25"
    static let id: Int = 20230925
    
    static let updatedWeight: Double = 75
    static let updatedSkeletalMusleMass: Double = 42
    static let updatedFatPercentage: Double = 12
    static let updatedDate: String = "2023.09.25"
    static let updatedId: Int = 20230925
    
    static let createDate: String = "2023.09.28"
    static let createId: Int = 20230928
}

다음과 같이 데이터 구조를 아예 정의해서 가져다가 쓰면 오타로 인한 이슈는 발생하지 않을 것이라고 생각했다.(나름 만족)

 

 

그리고 이것은 Read에 해당하는 테스트 코드이다. 

어디서 주워들었는데 메서드 이름은 테스트 코드이기 때문에 "알아보는 것이 제일 중요"하다고 했다. 

그래서 찾아보면 한글로 된 메서드들도 간간히 보인다. 

 

나 역시 마크 주석으로 어떤 테스트인지 작성하고 메서드 이름도 

"어떤 테스트"_"어떤 환경일 때"_"어떻게 작동해야 하나"를 중점적으로 작성했다. 

또한 //Given //When //Then 형식에 맞추니 가독성이 높아졌다고 느꼈다. 

    // MARK: - BodyInfoDataManager readBodyInfoData 메서드 테스트
    func testReadBodyInfoData_WhenBodyInfoDataExist_ShouldReadBodyInfoDataWithEqualValues() {
        // Given
        let expectedWeight = ExpectedBodyInfoData.weight
        let expectedSkeletalMuscleMass = ExpectedBodyInfoData.skeletalMusleMass
        let expectedFatPercentage = ExpectedBodyInfoData.fatPercentage
        let id = ExpectedBodyInfoData.id
        
        // When
        let bodyInfoData = sut.readBodyInfoData(id: id)
        
        // Then
        XCTAssertEqual(bodyInfoData?.weight, expectedWeight)
        XCTAssertEqual(bodyInfoData?.skeletalMuscleMass, expectedSkeletalMuscleMass)
        XCTAssertEqual(bodyInfoData?.fatPercentage, expectedFatPercentage)
    }

 

 

한 가지 고민되는 부분은 다음과 같다. 

    // MARK: - BodyInfoDataManager readBodyInfoData 메서드 테스트
    func testReadBodyInfoData_WhenBodyInfoDataExist_ShouldReadBodyInfoDataWithEqualValues() {
        // Given
        let expectedWeight = ExpectedBodyInfoData.weight
        let expectedSkeletalMuscleMass = ExpectedBodyInfoData.skeletalMusleMass
        let expectedFatPercentage = ExpectedBodyInfoData.fatPercentage
        let id = ExpectedBodyInfoData.id
        
        // When
        let bodyInfoData = sut.readBodyInfoData(id: id)
        
        // Then
        XCTAssertEqual(bodyInfoData?.weight, expectedWeight)
        XCTAssertEqual(bodyInfoData?.skeletalMuscleMass, expectedSkeletalMuscleMass)
        XCTAssertEqual(bodyInfoData?.fatPercentage, expectedFatPercentage)
    }

이 메서드는 데이터를 생성하는 것을 테스트 하는 메서드이다. 

여기서 When 부분을 보면

readBodyInfoData라는 메서드를 사용한다.

하지만 이 메서드는 바로 위해서 테스트하고자 했던 메서드인데 이걸 데이터를 확인하고자 사용해도 될지가 아직 미지수이다....

(궁금해.....)

 

 

 

 

좀 더 알아보도록 해야지

사실 테스트 코드를 공부하고 있지만 많은 자료가 있지는 않다..(좀 진입장벽이 높은것 같기도 하고)

그래서 아무래도 뇌피셜로 테스트코드를 작성하기도 했다. 그치만 그 덕분에 많은 고민을 했고 어떻게 해야 더 좋은 테스트코드일지 시행착오를 겪고 있는 것 같다! 



https://www.mongodb.com/docs/realm/sdk/swift/realm-files/configure-and-open-a-realm/

 

Configure & Open a Realm - Swift SDK — Realm

Docs Home → Realm When you open a realm, you can pass a Realm.Configuration that specifies additional details about how to configure the realm file. This includes things like:Pass a fileURL or in-memory identifier to customize how the realm is stored on

www.mongodb.com

https://www.mongodb.com/docs/realm/sdk/swift/test-and-debug/

 

Test and Debug - Swift SDK — Realm

If you want to work with a subset of an object's properties for testing, you can create a class projection. A class projection is a model abstraction where you can pass through, rename, or exclude realm object properties. While this feature simplifies view

www.mongodb.com

 

반응형