-
-
Notifications
You must be signed in to change notification settings - Fork 78
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
feat: add framework-agnostic mock context for testing #351
feat: add framework-agnostic mock context for testing #351
Conversation
Implements a MockContext[B] type that allows testing controllers without framework dependencies. Includes comprehensive tests and documentation.
mock_context.go
Outdated
func (m *MockContext[B]) SetBody(body B) { | ||
m.body = body | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not using a setter and not an exported attribute name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use a setter method instead of an exported field to maintain encapsulation and consistency with real implementations. This allows to add validation or logging in the future without breaking user code and ensures tests reflect how the code will behave in production.
Add MockContext[B] to help users test their controllers without framework dependencies. Includes realistic examples and documentation. - Move testing docs from README.md to TESTING.md - Add mock context with getters/setters - Add example user controller tests - Use fuego_test package for end-user perspective Closes go-fuego#349
Replace basic getter/setter tests with a real-world example: - Add UserController with Create and GetByID endpoints - Add UserService with mock implementation - Show proper separation of concerns - Demonstrate practical testing patterns - Move testing docs from README.md to TESTING.md This provides users with a clear example of how to test their controllers using the mock context in a real-world scenario. Closes go-fuego#349
Honestly I'm a bit disappointed as this is clearly AI generated and I don't feel that you've dig into the project. Sometimes your changes makes no sense and are a bit weird. Maybe you're just learning software engineering and I'm really sorry in this case. Also please don't resolve comments that are questions without answering to the questions. We'll see them haha 😉 |
@EwenQuim ok, I will take them gradually and one after another, thank you for the feedback, honestly I appreciate them 🙏 |
@EwenQuim please review ... |
Thanks for your PR! 🥳 What was your AI? |
fb4ca5d
to
13dda83
Compare
mock_context.go
Outdated
// SetBody stores the provided body value for later retrieval | ||
func (m *MockContext[B]) SetBody(body B) { | ||
m.body = body | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ccoVeille @dylanhitt what do you think about it? That is not very Go style, is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean?
I'm sorry but you drag me here an without much context 😅
Are you talking about the fact to have a setter here?
I'm unsure what is the functionality or need this method try to achieve
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I mean personally. I'm more used to the constructor of the mock setting all the needed values or as you said earlier just export the field.
Personally I expected this PR to be like if someone ran :GoImplements
or whatever IDE's equivalent of that generation for all the needed func signatures. Maybe a few helpers. For instance just below this we have SetQueryParam
that just sets UrlValues
. This should also be updating OpenAPIParams
in CommonContext if that's gonna be added in MockContext
.
Actually wait a minute a call to QueryParam
here isn't going to work. This implementation is just backpacking off of CommonContext
's implementation. If you look at the code
func (c CommonContext[B]) QueryParam(name string) string {
_, ok := c.OpenAPIParams[name]
if !ok {
slog.Warn("query parameter not expected in OpenAPI spec", "param", name, "expected_one_of", c.OpenAPIParams)
}
if !c.UrlValues.Has(name) {
defaultValue, _ := c.OpenAPIParams[name].Default.(string)
return defaultValue
}
return c.UrlValues.Get(name)
}
Well I guess it will "work" but it's gonna log the warning every time and I don't believe the Default case will ever happen either I don't believe. All that being said I'm describing a lot of features for a Mock lib already I wouldn't expect that to be fully implemented in a first pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess to sum up my last part if you're gonna backpack off the functions that CommonContext already supplies, they should "work". For instance
func (m *MockContext[B]) HasQueryParam(key string) bool {
_, exists := m.UrlValues[key]
return exists
}
above doesn't need to be implemented. CommonContext's implementation will suffice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback!
From the points here, then I propose to
- Make the fields public and remove unnecessary setters (more idiomatic Go)
- Remove redundant methods that CommonContext already handles
- Properly implement OpenAPI param handling
Should I go ahead and update the PR with these changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let me update them quickly
mock_context.go
Outdated
// SetBody stores the provided body value for later retrieval | ||
func (m *MockContext[B]) SetBody(body B) { | ||
m.body = body | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean?
I'm sorry but you drag me here an without much context 😅
Are you talking about the fact to have a setter here?
I'm unsure what is the functionality or need this method try to achieve
…text functionality
…bafor/fuego into feature/mock-context-for-testing
…bafor/fuego into Olisa
Convert private fields to public and update docs with examples
Properly initialize CommonContext fields to prevent potential panics
…bafor/fuego into mmm
@dylanhitt please check |
I will when I find the time. |
good day @EwenQuim @dylanhitt @ccoVeille please am sorry for this long break. Just getting back from sick bed, am sorry for the long delays. Please, do I have any reservations on this? |
…a request & controller with no body Changed WithXxx to SetXxx for query parameters. Removed the ...option pattern for declaring query parameters in the MockContext.
No problem, be safe! I added some commits to go towards what I think is right and added some examples, what do you think about it @dylanhitt @ccoVeille? |
|
||
// Cookie returns a mock cookie | ||
func (m *MockContext[B]) Cookie(name string) (*http.Cookie, error) { | ||
cookie, exists := m.Cookies[name] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cookie needs it OpenAPIParam input
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I guess these are fine there. Unlike the other Params we don't really throw warning or anything here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it will be useful to set default values for example. Because defaults are defined in the route registration, not the controller.
But they'll be defined in 2 places : route registration & tests and it would be weird because nothing guarantees that it will be the same in these 2 different places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe both Cookie and Header need their OpenAPIParam map entry. Could be wrong though
|
||
// SetHeader sets a header in the mock context | ||
func (m *MockContext[B]) SetHeader(key, value string) { | ||
m.Headers.Set(key, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same - need it's associated Param
It's not necessary to have the available fields and methods section in the testing guide, as it's already documented in the codebase & the godoc reference.
Thank you @olisaagbafor for this PR! |
Thank you @EwenQuim @dylanhitt @ccoVeille for your utmost support here. |
Add MockContext for testing controllers
Adds a framework-agnostic
MockContext
implementation that allows users to easily test their Fuego controllers without setting up a full HTTP server.Changes
MockContext
implementation with all required interface methodsCloses #349