Slide 1

Slide 1 text

How to Mock Protocols in Swift Sho Ikeda / @ikesyo Mobile Act KYOTO #1 2019-04-19 Fri #MobileAct

Slide 2

Slide 2 text

Sho Ikeda / @ikesyo • ͍͚͠ΐʔʗ஑ా ᠳ • ͸ͯͳ@ژ౎ • εϚʔτϑΥϯΞϓϦ։ൃ • iOS / Android / React Native • Swiftίϛολʔ • https://twitter.com/ikesyo • https://github.com/ikesyo

Slide 3

Slide 3 text

How to Mock Protocols in Swift • Manually ! • Sourcery: AutoMockable • SwiftyMocky • Cuckoo

Slide 4

Slide 4 text

Sourcery: AutoMockable • https://github.com/krzysztofzablocki/Sourcery • Mocks.md • AutoMockable.stencil • ର৅ͱͳΔͷ͸ • AutoMockable ͱ͍͏໊લͷϓϩτίϧʹ४ڌ • // sourcery: AutoMockable ͷΞϊςʔγϣϯίϝϯτͷ෇ ༩

Slide 5

Slide 5 text

Sourcery: AutoMockable • ϝιου • ݺ͹Ε͔ͨͲ͏͔ͷνΣοΫ: ճ਺͸෼͔Βͳ͍ • Ҿ਺λϓϧͷϓϩύςΟ: ݺ͹ΕͨҾ਺ͷνΣοΫ • ໭Γ஋ઃఆ༻ͷϓϩύςΟ • ϓϩύςΟఆٛ • ͔ͳΓγϯϓϧ • ֎෦Ҿ਺໊͕ಉҰɾܕҧ͍ͷΦʔόʔϩʔυ͸NG • ϓϩτίϧఆٛதʹ֎෦ϑϨʔϜϫʔΫͷܕ͕ొ৔͢Δ৔߹ɺࣗ෼ͰςϯϓϨʔτΛมߋ ͯ͠importΛॻ͖Ճ͑Δඞཁ͕͋Δ

Slide 6

Slide 6 text

Sourcery: AutoMockable • try! Swift Tokyo 2018 - Investing time into developer tools and experience • https://www.youtube.com/watch?v=yAQQ0cIxSF8 • SourceryΛ׆༻ͯ͠ςετΛॻ͘ϋʔυϧΛԼ͛Δ - Qiita

Slide 7

Slide 7 text

SwiftyMocky • https://github.com/MakeAWishFoundation/SwiftyMocky • Sourceryϕʔε • AutoMockableͷϚʔΫΛͦͷ··࢖༻ • ΑΓߴػೳͳςϯϓϨʔτͱϥϯλΠϜ • SourceryͷAutoMockableςϯϓϨʔτ͔ΒҠߦ͠΍͍͢

Slide 8

Slide 8 text

SwiftyMocky • δΣωϦΫεͷαϙʔτ • staticϝϯόʔͷαϙʔτ • ઃఆϑΝΠϧͰimport͢ΔϑϨʔϜϫʔΫΛࢦఆՄೳ • GivenʹΑΔελϒ • VerifyʹΑΔϝιουݺͼग़͠ͷݕࠪ • ճ਺΍Ҿ਺ • PerformʹΑΔϝιουͷϘσΟͷࠩ͠ସ͑

Slide 9

Slide 9 text

SwiftyMocky: Given Given(mock, .surname(for name: .value("Johnny"), willReturn: "Bravo")) Given(mock, .surname(for name: .any, willReturn: "Kowalsky")) print(mock.surname(for: "Johny")) // Bravo print(mock.surname(for: "Mathew")) // Kowalsky print(mock.surname(for: "Joanna")) // Kowalsky

Slide 10

Slide 10 text

SwiftyMocky: Given Given(mock, .surname(for name: .any, willReturn: "Bravo", "Kowalsky", "Nguyen")) print(mock.surname(for: "Johny")) // Bravo print(mock.surname(for: "Johny")) // Kowalsky print(mock.surname(for: "Johny")) // Nguyen print(mock.surname(for: "Johny")) // and again Bravo // ...

Slide 11

Slide 11 text

SwiftyMocky: Verify sut.usersStorage = mockStorage sut.saveUser(name: "Johny", surname: "Bravo") sut.saveUser(name: "Johny", surname: "Cage") sut.saveUser(name: "Jon", surname: "Snow") Verify(mockStorage, .storeUser(name: .value("Jon"), surname: .value("Snow"))) Verify(mockStorage, 3, .storeUser(name: .any, surname: .any)) Verify(mockStorage, 2, .storeUser(name: .value("Johny"), surname: .any)) Verify(mockStorage, .moreOrEqual(to: 2), .storeUser(name: .matching({ $0.count > 3 }}), surname: .any)) Verify(mockStorage, .never, .deleteUser(id: .any))

Slide 12

Slide 12 text

SwiftyMocky: Perform Perform( mock, .methodThatTakesCompletionBlock( completion: .any, perform: { completion in completion(true,nil) } ) )

Slide 13

Slide 13 text

Cuckoo • https://github.com/Brightify/Cuckoo • ಠࣗͷίʔυδΣωϨʔλʔ • SourceryϕʔεͰ͸ͳ͍͕ɺSourceKittenͱStencilΛ࢖͍ͬͯΔͷ͸ಉ͡ • Protocol͚ͩ͡Όͳ͘ɺClass΋αϙʔτ͍ͯ͠Δ • δΣωϦΫε͸ະαϙʔτ • staticϝϯόʔ΋ඇαϙʔτ • ͦͷଞͷػೳ͸SwiftyMockyͱḮ৭ͳͦ͞͏ • ߏจ͸ΑΓSwifty͔΋͠Εͳ͍

Slide 14

Slide 14 text

Cuckoo stub(mock) { stub in when(stub.greetWithMessage("Hello world")).then { message in print(message) } } stub(mock) { stub in when(stub.readWriteProperty.get).thenReturn(10) when(stub.readWriteProperty.set(anyInt())).then { print($0) } }

Slide 15

Slide 15 text

Cuckoo mock.readWriteProperty = 10 mock.readWriteProperty = 20 mock.readWriteProperty = 30 let argumentCaptor = ArgumentCaptor() verify(mock, times(3)).readWriteProperty.set(argumentCaptor.capture()) argumentCaptor.value // Returns 30 argumentCaptor.allValues // Returns [10, 20, 30]

Slide 16

Slide 16 text

! Happy Swift Mocking/Testing

Slide 17

Slide 17 text

WE ARE HIRING https://hatenacorp.jp/recruit/

Slide 18

Slide 18 text

Thank you Sho Ikeda / @ikesyo