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

Add mocked client + subclass of XCTestCase #2928

Open
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

Kithin
Copy link

@Kithin Kithin commented Dec 27, 2022

I have created a spy client, in order to stub the response and also being able to verify the request.

To reduce boilerplate code, I created a XCTVaporTestCase. You don't need to configure the application every time. And tearing it down. All is being handled by XCTVaporTestCase.

You just simply do this:

final class ExampleTests: XCTVaporTestCase {
     func test_example() throws {
           try client.stubResponse(httpStatus: .ok)
     }
}

Copy link
Member

@0xTim 0xTim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial comments - it would also be good to add this to a test to a) make sure it works and b) show how to use it

Sources/XCTVapor/XCTVaporTestCase.swift Outdated Show resolved Hide resolved
Sources/XCTVapor/TestDoubles/Spies/SpyClient.swift Outdated Show resolved Hide resolved
Sources/XCTVapor/TestDoubles/Spies/SpyClient.swift Outdated Show resolved Hide resolved
Sources/XCTVapor/TestDoubles/Spies/SpyClient.swift Outdated Show resolved Hide resolved
@Kithin
Copy link
Author

Kithin commented Dec 31, 2022

@0xTim can you maybe help me, with this compiling error:
Undefined symbol: _$s11Development9configureyy5Vapor11ApplicationCKF

In the sub class I created: XCTVaporTestCase, I have added this code on line 20:
try configure(app)

After that I got this error:
Cannot find 'configure' in scope

That's why I added this import:
import Development

But then I got this symbol error:
Undefined symbol: _$s11Development9configureyy5Vapor11ApplicationCKF

@0xTim
Copy link
Member

0xTim commented Dec 31, 2022

@Kithin that's because you're trying to use something that links XCTest in an executable which isn't possible. If you use it in a test similar to https://github.com/vapor/vapor/blob/main/Tests/VaporTests/ApplicationTests.swift#L104 (that file is probably a good place for it) it should work

@Kithin
Copy link
Author

Kithin commented Dec 31, 2022

Aaaah, so you mean, I should move this file in the test folder instead of the source folder?

But is it still accessible for people to use in their own tests?

@Kithin
Copy link
Author

Kithin commented Dec 31, 2022

That something is that the SpyClient I created or because that class is a subclass of XCTestCase, and this super class can only be executed in test?

@0xTim
Copy link
Member

0xTim commented Jan 1, 2023

The SpyClient should stay in XCTVapor but where you try to use it should be in a test case

@Kithin
Copy link
Author

Kithin commented Jan 1, 2023

@Kithin that's because you're trying to use something that links XCTest in an executable which isn't possible. If you use it in a test similar to https://github.com/vapor/vapor/blob/main/Tests/VaporTests/ApplicationTests.swift#L104 (that file is probably a good place for it) it should work

I have tried it, but then I get the same error as in my previous comment:

@0xTim can you maybe help me, with this compiling error:
Undefined symbol: _$s11Development9configureyy5Vapor11ApplicationCKF

In the sub class I created: XCTVaporTestCase, I have added this code on line 20:
try configure(app)

After that I got this error:
Cannot find 'configure' in scope

That's why I added this import:
import Development

But then I got this symbol error:
Undefined symbol: _$s11Development9configureyy5Vapor11ApplicationCKF

@Kithin
Copy link
Author

Kithin commented Jan 1, 2023

@Kithin that's because you're trying to use something that links XCTest in an executable which isn't possible. If you use it in a test similar to https://github.com/vapor/vapor/blob/main/Tests/VaporTests/ApplicationTests.swift#L104 (that file is probably a good place for it) it should work

I have tried it, but then I get the same error as in my previous comment, it's because the configure function is located in the executableTarget Development:

@0xTim can you maybe help me, with this compiling error:
Undefined symbol: _$s11Development9configureyy5Vapor11ApplicationCKF

In the sub class I created: XCTVaporTestCase, I have added this code on line 20:
try configure(app)

After that I got this error:
Cannot find 'configure' in scope

That's why I added this import:
import Development

But then I got this symbol error:
Undefined symbol: _$s11Development9configureyy5Vapor11ApplicationCKF

@0xTim
Copy link
Member

0xTim commented Jan 4, 2023

Can you push the current test case up?

@Kithin
Copy link
Author

Kithin commented Jan 8, 2023

Can you push the current test case up?

@0xTim I have pushed it. It's the latest commit: UPDATE - set mocked client

@familon16
Copy link

familon16 commented Jan 11, 2023 via email

@Kithin
Copy link
Author

Kithin commented Jan 15, 2023

@0xTim the test keeps failing on GitHub actions, but not locally. Can you perhaps help me?

@0xTim
Copy link
Member

0xTim commented Jan 16, 2023

@Kithin you're using the new generics syntax from Swift 5.7 that isn't available on older Swift versions. You'll need to find a work around

@Kithin
Copy link
Author

Kithin commented Jan 26, 2023

@0xTim do you have more feedback. And I also wanted to thank you for your help, when I was stuck.

Copy link
Member

@0xTim 0xTim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay - last few changes and I think we're good to go!

Sources/XCTVapor/TestDoubles/Spies/SpyClient.swift Outdated Show resolved Hide resolved
Sources/XCTVapor/TestDoubles/Spies/SpyClient.swift Outdated Show resolved Hide resolved
Kithin and others added 4 commits February 26, 2023 21:22
Co-authored-by: Tim Condon <0xTim@users.noreply.github.com>
Co-authored-by: Tim Condon <0xTim@users.noreply.github.com>
Co-authored-by: Tim Condon <0xTim@users.noreply.github.com>
@Kithin
Copy link
Author

Kithin commented Feb 26, 2023

@0xTim When I merge main into this feature branch, I don't get that merge conflict. But I have fixed the merge conflicts anyway. But the PR I still get the message: This branch has conflicts that must be resolved

@0xTim
Copy link
Member

0xTim commented Feb 26, 2023

@Kithin It's in the application tests, I can't see the test you added anymore?

@Kithin
Copy link
Author

Kithin commented Feb 26, 2023

@Kithin It's in the application tests, I can't see the test you added anymore?

I didn't added a new test, I updated this test: testBoilerplate

@0xTim
Copy link
Member

0xTim commented Feb 27, 2023

@Kithin Hmm I see. I can't check the merge conflicts because I don't have access to the fork. So the easiest thing to probably do is close the PR, update your fork, then create a new branch and copy the code across. Let's put the test for the client in its own test case as well

@SpaceboatDVLP
Copy link

SpaceboatDVLP commented Sep 5, 2023

Would it make sense to add a configure function within SpyClient in case someone wants to init a stubbed response within a unit test rather than setting up the client within the XCTestCase? For example:

static func configure<T: Content>(on app: Application, with response: T) throws {
    let client = SpyClient(eventLoop: app.eventLoopGroup.next())
    app.clients.use { _ in
        return client
    }
    try client.stubResponse(httpStatus: .ok, responseData: response)
}

Then you could use it within a unit test like this:

let mockResponse = MockResponse(message: "nice")
try SpyClient.configure(on: app, with: mockResponse)

Thanks for this by the way.

@0xTim
Copy link
Member

0xTim commented Sep 6, 2023

@SpaceboatDVLP that pattern would be to store the instance of the SpyClient on the XCTestCase

So in your test case you'd do

self.spyClient.stubResponse(httpStatus: .ok, responseData: response)

That allows you to also inspect the request send to the client etc

There's nothing stopping you adding the configure function in your code of course

@0xTim 0xTim mentioned this pull request Mar 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants