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

FetchRecipeDetailUseCaseTests를 생성하였습니다 #19

Merged
merged 13 commits into from
Jul 23, 2024
22 changes: 22 additions & 0 deletions HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/Recipe.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,25 @@ struct Recipe {
let likeCount: Int
let createdAt: Date
}

extension Recipe {

static func dummyRecipe() -> Recipe {
.init(
id: 1,
type: .coffee,
name: "",
description: "",
writer: .init(
id: 1,
profileImage: "",
nickname: "",
createdAt: Date()
),
imageUrls: [],
isLikedByCurrentUser: false,
likeCount: 0,
createdAt: Date()
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//
// FetchRecipeDetailUseCaseTests.swift
// HomeCafeRecipesTests
//
// Created by 김건호 on 7/17/24.
//

import Foundation
import XCTest

import RxSwift

@testable
import HomeCafeRecipes

final class FetchRecipeDetailUseCaseTests: XCTestCase {

var fetchRecipeDetailRepository: FetchRecipeRepositoryMock!
var disposeBag: DisposeBag!

final class FetchRecipeRepositoryMock: RecipeDetailRepository {
var fetchRecipeDetailCallCount: Int = 0
var fetchRecipeDetailStub: Single<Recipe> = .just(Recipe.dummyRecipe())
func fetchRecipeDetail(recipeID: Int) -> Single<Recipe> {
fetchRecipeDetailCallCount += 1
return fetchRecipeDetailStub
}
}

func createUseCase() -> FetchRecipeDetailUseCase {
let usecase = FetchRecipeDetailUseCaseImpl(
repository: fetchRecipeDetailRepository
)
return usecase
}

override func setUpWithError() throws {
fetchRecipeDetailRepository = .init()
disposeBag = .init()
}
}

extension FetchRecipeDetailUseCaseTests {

func test_execute를_호출하면_RecipeDetailRepository의_fetchRecipeDetail을_호출합니다(){

// Given

let usecase = createUseCase()
fetchRecipeDetailRepository.fetchRecipeDetailStub = .just(Recipe.dummyRecipe())

// When

usecase.execute(recipeID: 1)
.subscribe()
.disposed(by: disposeBag)

// Then

XCTAssertEqual(fetchRecipeDetailRepository.fetchRecipeDetailCallCount, 1)
}

func test_RecipeDetailRepository의_성공응답이오면_Recipe를_반환합니다(){

// Given

let usecase = createUseCase()
let recipe = Recipe.dummyRecipe()
fetchRecipeDetailRepository.fetchRecipeDetailStub = .just(recipe)
let expectation = self.expectation(description: "Fetch Recipe Success")

// When

usecase.execute(recipeID: 1)
.subscribe(onSuccess: { result in
if case .success(let fetchedRecipe) = result {
// Then

XCTAssertEqual(fetchedRecipe.id, recipe.id)
expectation.fulfill()
} else {
XCTFail("Expected success but got failure")
}
}, onFailure: { error in
XCTFail("Expected success but got error: \(error)")
})
.disposed(by: disposeBag)

wait(for: [expectation], timeout: 1.0)
XCTAssertEqual(fetchRecipeDetailRepository.fetchRecipeDetailCallCount, 1)
}

func test_RecipeDetailRepository의_실패응답이오면_Error를_반환합니다() {

// Given

let usecase = createUseCase()
let error = NSError(domain: "TestError", code: -1)
fetchRecipeDetailRepository.fetchRecipeDetailStub = .error(error)
let expectation = self.expectation(description: "Fetch Recipe Failure")

// When

usecase.execute(recipeID: 1)
.subscribe(onSuccess: { result in
if case .failure(let receivedError as NSError) = result {
// Then

XCTAssertEqual(receivedError.domain, error.domain)
XCTAssertEqual(receivedError.code, error.code)
expectation.fulfill()
} else {
XCTFail("Expected failure but got success")
}
}, onFailure: { error in
XCTFail("Expected failure but got error: \(error)")
})
.disposed(by: disposeBag)

wait(for: [expectation], timeout: 1.0)
XCTAssertEqual(fetchRecipeDetailRepository.fetchRecipeDetailCallCount, 1)

}

}
111 changes: 111 additions & 0 deletions HomeCafeRecipes/HomeCafeRecipesTests/RecipeDeatilInteractorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//
// RecipeDeatilInteractorTests.swift
// HomeCafeRecipesTests
//
// Created by 김건호 on 7/9/24.
//

import Foundation
import XCTest

import RxSwift

@testable
import HomeCafeRecipes

final class RecipeDetailInteractorTests: XCTestCase {
var fetchRecipeDetailUsecase: FetchRecipeDetailUseCaseMock!
var delegate: RecipeDetailInteractorDelegateMock!

final class FetchRecipeDetailUseCaseMock: FetchRecipeDetailUseCase {
var executeCallCount: Int = 0
var executeStub: Single<Result<Recipe, Error>> = .just(.failure(NSError()))
func execute(recipeID: Int) -> Single<Result<Recipe, Error>> {
executeCallCount += 1
return executeStub
}
}

final class RecipeDetailInteractorDelegateMock: RecipeDetailInteractorDelegate {
var fetchedCallCount: Int = 0
var fetchedRecipeResult: Result<Recipe, Error>?
func fetchedRecipe(result: Result<Recipe, Error>) {
fetchedCallCount += 1
fetchedRecipeResult = result
}
}

func createInteractor(recipeID: Int = 0) -> RecipeDetailInteractor {
let interactor = RecipeDetailInteractorImpl(
fetchRecipeDetailUseCase: fetchRecipeDetailUsecase,
recipeID: recipeID
)

interactor.delegate = delegate
return interactor
}

override func setUpWithError() throws {
fetchRecipeDetailUsecase = .init()
delegate = .init()
}
}

// MARK: viewDidLoad

extension RecipeDetailInteractorTests {

func test_화면이_로드될때_FetchRecipeDetailUsecase를_호출합니다() {
// given
let interactor = createInteractor()

// when
interactor.viewDidLoad()

// then
XCTAssertEqual(self.fetchRecipeDetailUsecase.executeCallCount, 1)
}

func test_FetchRecipeDetailUsecase의_성공응답이오면_Delegate로_성공을_전달합니다() {
// given
let interactor = createInteractor()
let recipe = Recipe.dummyRecipe()
fetchRecipeDetailUsecase.executeStub = .just(.success(recipe))

// when
interactor.viewDidLoad()

// then
XCTAssertEqual(self.fetchRecipeDetailUsecase.executeCallCount, 1)
XCTAssertEqual(self.delegate.fetchedCallCount, 1)

if case .success(let fetchedRecipe)? = delegate.fetchedRecipeResult {
XCTAssertEqual(fetchedRecipe.id, recipe.id)
} else {
XCTFail("Expected success but got failure or nil")
}
}

func test_FetchRecipeDetailUsecase의_실패응답이오면_Delegate로_실패를_전달합니다() {

// given
let interactor = createInteractor()
let error = NSError(domain: "TestError", code: -1)
fetchRecipeDetailUsecase.executeStub = .just(.failure(error))

// when
interactor.viewDidLoad()

// then
XCTAssertEqual(self.fetchRecipeDetailUsecase.executeCallCount, 1)
XCTAssertEqual(self.delegate.fetchedCallCount, 1)

if case .failure(let fetchedError as NSError) = delegate.fetchedRecipeResult {
XCTAssertEqual(fetchedError.domain, error.domain)
XCTAssertEqual(fetchedError.code, error.code)
} else {
XCTFail("Expected success but got failure or nil")
}

}
}
Loading