我是iOS开发单元测试的新手,我有一个如下的视图模型
class PostsViewViewModel {
private let serviceRequest: NetworkRequestProtocol
public private(set) var requestOutput: PassthroughSubject<RequestOutput, Never> = .init()
private var cancellables = Set<AnyCancellable>()
init(
request: NetworkRequestProtocol,
user: LoginUserModel,
codeDataManager: CoreDataManagerProtocol) {
serviceRequest = request
loadPostsFromServerFor(user: user)
}
private func loadPostsFromServerFor(user: LoginUserModel) {
Task {
do {
let postsRecived = try await serviceRequest.callService(
with: ServiceEndPoint.fetchPostsForUser(id: user.userid),
model: [PostModel].self,
serviceMethod: .get
)
if postsRecived.isEmpty {
requestOutput.send(.fetchPostsDidSucceedWithEmptyList)
} else {
recievedRawPostsModel = postsRecived
createPostModelsFromPostRecieved(postsRecived)
requestOutput.send(.fetchPostsDidSucceed)
}
} catch {
requestOutput.send(.fetchPostsDidFail)
}
}
}
}
extension PostsViewViewModel {
enum RequestOutput {
case fetchPostsDidFail
case fetchPostsDidSucceed
case fetchPostsDidSucceedWithEmptyList
case reloadPost
}
}
现在我创建了一个ViewModel的测试类,如下所示
final class PostViewViewModelTest: XCTestCase {
let userInput: PassthroughSubject<PostsViewViewModel.UserInput, Never> = .init()
private var cancellable = Set<AnyCancellable>()
private let mockUser = LoginUserModel(userid: 1)
private let coreDataManager = CoreDataStackInMemory()
private var sutPostViewModel: PostsViewViewModel!
override func setUp() {
sutPostViewModel = PostsViewViewModel(
request: MockNetworkRequestPostSuccess(),
user: mockUser, codeDataManager: coreDataManager
)
}
override func tearDown() {
sutPostViewModel = nil
}
func testPostsViewViewModel_WhenPostModelLoaded_NumberOfRowsSouldBeMoreThanZero() {
// let postViewModel = sutPostViewModel!
self.sutPostViewModel.requestOutput
//.receive(on: DispatchQueue.main)
.sink { [weak self] output in
XCTAssertTrue(output == .fetchPostsDidSucceed)
XCTAssertTrue((self?.sutPostViewModel.numberOfRowsInPostTableView)! > 0)
}
.store(in: &cancellable)
}
func testPostsViewViewModel_WhenPostModelLoaded_GetPostAtGivenIndexPathMustHaveEqualPostID() {
// let postViewModel = sutPostViewModel!
self.sutPostViewModel.requestOutput
.receive(on: DispatchQueue.main)
.sink { [weak self] output in
print(output == .reloadPost)
let post = self?.sutPostViewModel.getPost(at: IndexPath(row: 0, section: 0))
let postModel: [PostModel] = JSONLoader.load("Posts.json")
XCTAssertTrue(post.postID == postModel[0].id)
}
.store(in: &cancellable)
}
}
但是测试用例在访问sutpostViewModel时崩溃了。我不明白我在这里做错了什么。
调试时,我发现在接收和测试崩溃之前调用了tearDown()。
1条答案
按热度按时间dojqjjoe1#
我觉得你可能需要一个预期。
您有异步代码,因此
sink
在测试方法运行后执行。此时,tearDown
已被调用,sut
设置为nil