Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EnvironmentInjection crashes under certain conditions #338

Open
shuufei opened this issue Oct 1, 2024 · 0 comments
Open

EnvironmentInjection crashes under certain conditions #338

shuufei opened this issue Oct 1, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@shuufei
Copy link

shuufei commented Oct 1, 2024

When I run the test under certain conditions, it crashes on EnvironmentInjection in ViewInspector.

I can't identify the conditions that cause the crash because I just changed some code that I don't think is the cause of the crash and I can see the result of whether it crashes or not.

Also, the result does not change with each execution, but always crashes under certain conditions.

Environment

  • XCode: 15.4
  • ViewInspector: 0.10.0
  • Run Destination: Simulator iPhone 15 (17.5)

Crash Details

EXC_BAD_ACCESS is occurring at line 47 of EnvironmentInjection.

スクリーンショット 2024-10-01 11 51 38

Crashing Code

View under test↓

import SwiftUI

@MainActor
class ViewModel: ObservableObject {
    @Published var count: Int = 0
}

struct ContentView: View {
    @State var model: ModelA?
    
    @EnvironmentObject var viewModel: ViewModel
    
    #if DEBUG
    internal var didAppear: ((Self) -> Void)?
    #endif

    var body: some View {
        VStack {
            Text("Count: \(viewModel.count)")
            Button {
                viewModel.count += 1
            } label: {
                Text("increment")
            }
            Button {
                viewModel.count -= 1
            } label: {
                Text("decrement")
            }
        }
        .padding()
        .onAppear {
            #if DEBUG
            self.didAppear?(self)
            #endif
        }
    }
}

struct ModelA: Codable {
    let id: String
    var property1: String
    let property2: String
    var property3: String
    let property4: String
    let property5: String
    let property6: String
    var property7: [String]
    let property8: Date
    let property9: Date?
    var property10: Double?
    var property11: ModelB?
    var property12: Status

    struct ModelB: Codable, Hashable {
        let id: String
        var property1: [String]
    }

    enum Status: String, Codable {
        case ready = "READY"
        case running = "RUNNING"
    }
}

Test code↓

import XCTest
import ViewInspector
@testable import ViewInspectorSample

final class ViewInspectorSampleTests: XCTestCase {
    override func setUpWithError() throws {
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDownWithError() throws {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }
    
    @MainActor
    func testCounter() throws {
        var sut = ContentView()
        
        let exp = sut.on(\.didAppear) { view in
            let countText = try view.vStack().text(0).string()
            XCTAssertEqual(countText, "Count: 0")
            try view.find(button: "increment").tap()
            let updatedText = try view.find(ViewType.Text.self).string()
            XCTAssertEqual(updatedText, "Count: 1")
        }
        ViewHosting.host(view: sut.environmentObject(ViewModel()))
        wait(for: [exp], timeout: 0.1)
    }
}

If I set Run Destination to Simulator iPhone 14 (16.0), the crash does not occur.

No Crash Code

Fixed the value type ModelA defined in @State.
Just commented out one property.
The value defined in @State is not used anywhere in the View.

With this code, the test succeeds without crashing.
No change in test code.

import SwiftUI

@MainActor
class ViewModel: ObservableObject {
    @Published var count: Int = 0
}

struct ContentView: View {
    @State var model: ModelA?
    
    @EnvironmentObject var viewModel: ViewModel
    
    #if DEBUG
    internal var didAppear: ((Self) -> Void)?
    #endif

    var body: some View {
        VStack {
            Text("Count: \(viewModel.count)")
            Button {
                viewModel.count += 1
            } label: {
                Text("increment")
            }
            Button {
                viewModel.count -= 1
            } label: {
                Text("decrement")
            }
        }
        .padding()
        .onAppear {
            #if DEBUG
            self.didAppear?(self)
            #endif
        }
    }
}

struct ModelA: Codable {
    let id: String
    var property1: String
    let property2: String
    var property3: String
    let property4: String
    let property5: String
    let property6: String
    var property7: [String]
//    let property8: Date  <--------------- comment out
    let property9: Date?
    var property10: Double?
    var property11: ModelB?
    var property12: Status

    struct ModelB: Codable, Hashable {
        let id: String
        var property1: [String]
    }

    enum Status: String, Codable {
        case ready = "READY"
        case running = "RUNNING"
    }
}

Not only property8, but removing other properties from ModelA or changing the type definition will no longer cause crashes.


We are strongly considering adopting ViewInspector for our project.
I wish you the best of luck in resolving this issue. Best regards.

@nalexn nalexn added the bug Something isn't working label Nov 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants