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

Implement service and endpoint mocking support in tests #1005

Merged
merged 7 commits into from
Jan 18, 2024

Conversation

DomBlack
Copy link
Contributor

This PR implements three new features into the et (Encore Testing) package.

  • et.MockEndpoint allows you to replace a specific endpoint during a test with another implementation.
  • et.MockService allows you to replace entire services during a test with either a different instance of the service struct or with a wholly mocked-out object.
  • et.EnableServiceInstanceIsolation allows you to force a test to have it's own isolated instance of any service struct that is accessed during that test.

All three of these functions can be called in the test entry point (TestMain) or in your tests themselves. They all cascade their behaviour down from the point called to any sub-tests as well.

@DomBlack DomBlack requested a review from eandre January 18, 2024 12:28
@encore-cla
Copy link

encore-cla bot commented Jan 18, 2024

All committers have signed the CLA.

Copy link

github-actions bot commented Jan 18, 2024

Test Results

  2 files  +    1  227 suites  +65   14m 55s ⏱️ - 9m 15s
742 tests +  204  739 ✅ +  214  3 💤 +3  0 ❌  - 4 
742 runs   - 1 868  739 ✅  - 1 858  3 💤 +3  0 ❌  - 4 

Results for commit c597051. ± Comparison against base commit 4092684.

This pull request removes 18 and adds 222 tests. Note that renamed tests count towards both.
encr.dev/e2e-tests ‑ TestRun/encore_currentrequest
encr.dev/e2e-tests ‑ TestRun/et_override_user
encr.dev/e2e-tests ‑ TestRun/et_override_user_authdata
encr.dev/e2e-tests ‑ TestRun/experiment_local_secrets_override
encr.dev/e2e-tests ‑ TestRun/fallback_routes
encr.dev/e2e-tests ‑ TestRun/graceful_shutdown
encr.dev/e2e-tests ‑ TestRun/pubsub_method_handler
encr.dev/e2e-tests ‑ TestRun/pubsub_ref
test/svc ‑ TestProcClosedOnCtxCancel
test/svc ‑ TestRun
…
encore.dev/appruntime/apisdk/api ‑ TestDescGeneratesTrace
encore.dev/appruntime/apisdk/api ‑ TestDescGeneratesTrace/echo
encore.dev/appruntime/apisdk/api ‑ TestDescGeneratesTrace/invalid
encore.dev/appruntime/apisdk/api ‑ TestDescGeneratesTrace/raw
encore.dev/appruntime/apisdk/api ‑ TestDescGeneratesTrace/unauthenticated
encore.dev/appruntime/apisdk/api ‑ TestDesc_EndToEnd
encore.dev/appruntime/apisdk/api ‑ TestDesc_EndToEnd/echo
encore.dev/appruntime/apisdk/api ‑ TestDesc_EndToEnd/invalid
encore.dev/appruntime/apisdk/api ‑ TestDesc_EndToEnd/unauthenticated
encore.dev/appruntime/apisdk/api ‑ TestRawEndpointOverflow
…

♻️ This comment has been updated with latest results.

Copy link
Member

@eandre eandre left a comment

Choose a reason for hiding this comment

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

Looks great overall!

Comment on lines +451 to +465
if mockedAPI, found := c.server.testingMgr.GetAPIMock(d.Service, d.Endpoint); found && mockedAPI.Function != nil {
function, err := d.getMockFunction(mockedAPI)
if err != nil {
return respData, errs.Wrap(err, "unable to call mocked API due to an issue with the mock")
}
return d.mockedCall(c, function, req)
} else if mockedService, found := c.server.testingMgr.GetServiceMock(d.Service); found && mockedService != nil {
method, err := d.getMockMethod(mockedService)
if err != nil {
return respData, errs.Wrap(err, "unable to call mocked API due to an issue with the mock")
}
return d.mockedCall(c, method, req)
} else {
return d.internalCall(c, req)
}
Copy link
Member

Choose a reason for hiding this comment

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

Would be nice to extract this to a d.testingCall method like for d.internalCall below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The extraction is already d.mockedCall - seemed a little rediciously do have let another d.testingCall then d.mockedCall, d.internalCall and d.externalCall

Given that Call was the place where we decided what actual type of call we're going to make, it felt right to keep the logic all here

Copy link
Member

Choose a reason for hiding this comment

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

Ah fair

holder InstanceHolder[T]
}

type InstanceHolder[T any] struct {
Copy link
Member

Choose a reason for hiding this comment

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

Would be nice to document why this exists

@@ -357,15 +357,15 @@ func (i BuilderImpl) GenUserFacing(ctx context.Context, p builder.GenUserFacingP
// Service structs are not needed if there is no implementation to be generated
svcStruct := option.None[*codegen.VarDecl]()

buf.Reset()
Copy link
Member

Choose a reason for hiding this comment

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

What's the reason for the change here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You introduced a bug in v2 which has been iterating me all year ;)

Without the reset, it causes us to generate empty encore.gen.go files when they are not needed. (As you unconditionally always add the prelude comments). I explicly didn't do this in v1, and this fixes it in v2.

Copy link
Member

Choose a reason for hiding this comment

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

Ah nice. We also have an outstanding issue where we keep encore.gen.go files around after a service has been renamed. Think that would be easy to address, too, or is that a separate issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seperate issue, mainly because we don't track services in the CLI so we have no way of detecting that easily (apart from maybe looking for encore.gen.go files being the only thing in a folder - but I say let's keep that as a separate issue

v2/parser/apis/api/usage.go Outdated Show resolved Hide resolved
v2/codegen/apigen/userfacinggen/userfacinggen.go Outdated Show resolved Hide resolved
Co-authored-by: André Eriksson <andre@encore.dev>
eandre
eandre previously approved these changes Jan 18, 2024
@DomBlack DomBlack enabled auto-merge (squash) January 18, 2024 13:31
@DomBlack DomBlack requested a review from eandre January 18, 2024 13:31
@DomBlack DomBlack merged commit 4fcc90a into main Jan 18, 2024
5 checks passed
@DomBlack DomBlack deleted the enc-2006-implement-more-et-functionality branch January 18, 2024 13:32
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.

2 participants