2
\$\begingroup\$

I'm studying unit testing in swift and I would like to know if I'm doing the right way.

Here I have the model

struct ChangePasswordRequest: Encodable {
 var email: String
 var newPassword: String
 var token: String
}

And here the unit test

import XCTest
@testable import MyProject
class ChangePasswordRequestTests: XCTestCase {
 var changePasswordRequest: ChangePasswordRequest!
 override func tearDown() {
 // Put teardown code here. This method is called after the invocation of each test method in the class.
 changePasswordRequest = nil
 super.tearDown()
 }
 func testChangePasswordRequest() {
 // given
 let email = "[email protected]"
 let newPassword = "abc123"
 let token =
 """
 rF1rHbYVCpcfyo6K2e7Q68QvKYdeOMt0vDXYehggGU3kx8XiuGmQylXabxbGAyUmSK9RnbL
 """
 // when
 changePasswordRequest = ChangePasswordRequest(email: email, newPassword: newPassword, token: token)
 let requestJSON = """
 {"email":"\(email)","token":"\(token)","newPassword":"\(newPassword)"}
 """
 changePasswordRequest = ChangePasswordRequest(email: email, newPassword: newPassword, token: token)
 guard let encodedRequest = try? JSONEncoder().encode(changePasswordRequest) else {
 XCTFail()
 return
 }
 // then
 XCTAssertEqual(String(data: encodedRequest, encoding: .utf8)!, requestJSON, "Any JSON key differs from model.")
 }
}

I never worked with unit test. It's possible to improve this test?

200_success
146k22 gold badges190 silver badges479 bronze badges
asked Dec 19, 2017 at 12:47
\$\endgroup\$
0

2 Answers 2

2
\$\begingroup\$

Some hints on Unit tests.

  • Use dependency injection to make testing easier
  • Create mocks to eliminate all external dependencies in tests
  • Test units of code (functions, methods, classes)

Example of testable class:

class UserManager: UserManagerType {
 let database: DatabaseType
 init(database: DatabaseType) {
 self.database = database
 }
 func getUser(withId id: String) -> User? {
 return database.getItem(withPredicate: "id == \(id)")
 }
 func getAdmins() -> [User] {
 return database.getItems(withPredicate: "type == admin")
 }
}
protocol DatabaseType { 
 func getItems(withPredicate predicate: String) -> [User]
 func getItem(withPredicate predicate: String) -> User?
} 

Tests:

// create mock for database.
// Try to avoid any external dependencies in tests
class DatabaseMock: DatabaseType {
 var itemsToReturn: [User] = []
 var userToReturn: User?
 func getItems(withPredicate predicate: String) -> [User] {
 return itemsToReturn
 }
 func getItem(withPredicate predicate: String) -> User? {
 return userToReturn
 }
}
// actual test case
class UserManagerTests: XCTestCase {
 var database: DatabaseMock = DatabaseMock()
 var manager: UserManager!
 // setup before each test
 func setUp() {
 database = DatabaseMock()
 manager = UserManager(database: database)
 }
 func testReturnsCorrectUserForId() {
 let expectedUser = User(id: "123")
 database.userToReturn = expectedUser
 let actualUser = manager.getUser(withId: "123")
 XCTAssertNotNil(actualUser)
 XCTAsseerEqual(actualUser.id, expectedUser.id)
 }
 // other tests ...
}

This is not the best example (because UserManager is just a wrapper around database) but I hope you have got some ideas of how write unit tests

answered Jan 3, 2018 at 15:19
\$\endgroup\$
0
1
\$\begingroup\$

You should think about WHAT you test.

You just test in your UnitTest the Json encoder. But i think the json encoder is still good tested and you not need to test it again.

You should test business logic (methods/functions) you have written and cover the code with the test

answered Dec 20, 2017 at 5:44
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.