-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
QuarkusComponentTest #33607
QuarkusComponentTest #33607
Conversation
Thanks for your pull request! The title of your pull request does not follow our editorial rules. Could you have a look?
|
2902c7f
to
b4dc722
Compare
🙈 The PR is closed and the preview is expired. |
I like this very much! I only looked at the code very briefly, but didn't find any glaring issue. Will review properly next week. |
I'll have a look next week. |
, looking next week! |
This comment has been minimized.
This comment has been minimized.
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.
This is awesome, I will look at adding support for continuous testing. It's a real pity we can't call this QuarkusUnitTest
and rename QuarkusUnitTest
to QuarkusExtensionTest
.
My only concern is that our testing story might be getting a but muddled now. We need to be sure that we have a good docs/guides that explain to beginners what the different options are and the use cases for them.
Yeah, I'm afraid of the same... We totally need to do an excellent job explaining when to use what |
Meanwhile, this awesome work, and a big changeset, isn't merged, because we need to get the bigger picture straight. I think as soon as we document any names it's very hard to change them, but does it make sense to split this into something which is mergeable, but we don't tell people about it. Then it's a question of designing the optimal user experience, which might include changing the names of other things, and possibly also these things ... and bringing in the documentation once we're happy with the names and relationships of everything? |
@mkouba, in this example, can I check my understanding?
The expectation is that the injected
If I wanted two things to be real, could I add two
? |
Sorry, me again. :) Would it be correct to say that the behaviour of QuarkusComponentTest is to make everything except core CDI and the thing listed as the annotation value a mock? As a straw man, here are some alternative programming models. It’s the same core code and user need as what @mkouba implemented, just a different window dressing. Option A
Here, we have the same confusion where ‘@Inject’ is actually injecting a mock, but at least there’s a clear distinction between the ‘inject a mock’ annotation and the ‘make this real’ annotation. The behaviour of QuarkusTest is now rather ambiguous/broad, depending on the presence of the mockEverything attribute. An alternative model would be an @MockEverything annotation, but I think the attribute would be simpler to implement and clearer. One thing I like about this is the slight improvement in DRYness. I don’t have to specify Option B, de-mocking
I think this one is evil in terms of the semantics, and nightmarish to implement. It's also my favourite. :) The idea is that goFast=true conveys the intention (Quarkus, please be Sir-Mock-A-Lot, and I am willing to sacrifice accuracy). The semantics of @Inject are sort of the same as normal - if you use @Inject, it’s real - but with the added wrinkle here, that @Inject is actually a de-mocking mechanism. So it drags the thing back from the land of the mocks, to the land of the living. If you use @Inject, you must want it to be real. Then, it’s clear that to get a mock, you’d have to use @InjectMock. If we don’t want to bring in the The nice thing about this is that, until you think about it too hard, the semantics and programming model seem to be exactly what people are used to. |
On a side note, one thing that I believe this feature will result in, is people opting for Panache Repository instead of Panache Active Record - unless we also integrate with |
It's a mocked dependency. By default, a Mockito mock is used. But a user can provide any type of mock through the programmatic API, i.e. no mocking library needs to be used.
More or less correct. The "real" is not a good name though. All the beans are real, but only the components (and some built-in beans) are discovered/created from the classes.
Nope, you can just do
I think so. The goal is to test the components listed in the annotation or otherwise passed to the |
@geoand Good point. But I have no idea how |
@FroMage can enlighten us :) |
Interesting ideas. The only advantage of "explicit" components definition is that you don't need to inject your components at all but use programmatic lookup in the test instead (e.g.
On the other hand, you need to specify the
What's the difference between
That's basicaly what we have now, except that you want the components to be collected from the test injection points and reuse the
In that case, we should probably introduce a new annotation in the |
We could also mark this as an experimental/unstable feature, or? |
+1 for experimental. I would also update the Javadoc to reflect this |
Next round of changes:
A simple test now looks like: @QuarkusComponentTest
@TestConfigProperty(key = "bar", value = "true")
public class FooTest {
@Inject
Foo foo;
@ConfigureMock
Charlie charlie;
@Test
public void testPing() {
Mockito.when(charlieMock.ping()).thenReturn("OK");
assertEquals("OK", foo.ping());
}
} |
This comment has been minimized.
This comment has been minimized.
- a JUnit extension to ease the testing of components and mocking of their dependencies == Lifecycle - the CDI container is started and a dedicated SmallRyeConfig is registered during the before all test phase - the container is stopped and the config is released during the after all test phase - the fields annotated with jakarta.inject.Inject are injected after a test instance is created and unset before a test instance is destroyed - the dependent beans injected into fields annotated with jakarta.inject.Inject are correctly destroyed before a test instance is destroyed - the CDI request context is activated and terminated per each test method == Auto Mocking Unsatisfied Dependencies - the test does not fail if a component injects an unsatisfied dependency - instead, a synthetic bean is registered automatically for each combination of required type and qualifiers of an injection point that resolves to an unsatisfied dependency - the bean has the Singleton scope so it's shared across all injection points with the same required type and qualifiers - the injected reference is an unconfigured Mockito mock. You can inject the mock in your test and leverage the Mockito API to configure the behavior == Custom Mocks For Unsatisfied Dependencies Sometimes you need the full control over the bean attributes and maybe even configure the default mock behavior. You can use the mock configurator API via the QuarkusComponentTest#mock(Class) method. == Configuration A dedicated SmallRyeConfig is registered during the before all test phase. Moreover, it's possible to set the configuration properties via the configProperty(String, String) method. If you only need to use the default values for missing config properties, then the useDefaultConfigProperties() might come in useful. Co-authored-by: Stuart Douglas [email protected]
Failing Jobs - Building 887708b
Full information is available in the Build summary check run. Failures⚙️ Native Tests - Amazon #- Failing: integration-tests/amazon-lambda integration-tests/amazon-lambda-http
📦 integration-tests/amazon-lambda✖
📦 integration-tests/amazon-lambda-http✖
|
I have another thought. Do you think it's a valid use case for people to use If it was a valid use case, the cleanest way to support it would be to use
which changed the behaviour of Another way of getting that behaviour, but with the The drawback of this idea is
|
I think that it's getting harder and harder to follow this discussion. I suggest we merge this as is (it's an experimental feature anyway), then create a new topic for follow-up discussions in https://github.com/quarkusio/quarkus/discussions and tune up the API and docs in follow-up PRs. |
@mkouba I think merging makes sense. From my perspective, the changes to
I think we may have more work to do to explore the UX and technical aspects of the edge cases where these new annotations get combined with other annotations in ways we don't expect, but that can be done post-merge. |
I'm going to merge this PR; the Native Tests - Amazon failures are unrelated. |
Well, why do you think this makes it better to use Repositories? |
Repositories are trivial to mock. |
Well, sure, but more trivial than active records? PanacheMock.mock(Person.class); Because that's all it takes to get the same thing as here, or in the repo pattern: @InjectMock
PersonRepository personRepository; Sure, in this case you will replace |
That's my point. Users will have to include |
I'm not sure it's going to be easier to use repositories than adding one Maven dependency to get active records mocked ;) But OK, if users ask us about this, we know we can enhance the new |
https://groups.google.com/g/quarkus-dev/c/gMgnPb_NzgU
TODO