Comments (5)
Then the documentation is contradictory: https://junit.org/junit5/docs/current/user-guide/#extensions-registration-programmatic Note the examples that reference the field. How can that work if there is no state? Also note that ServiceUseExtension must be instantiated programmatically.
from osgi-test.
Possibly the documentation is a little misleading. But I couldn't see the example that you referred to where it references a field. Perhaps you're referring to the Kotlin example? I'm far from a Kotlin guru, but I think that server.serverUrl
in Kotlin is equivalent to server.getServerURL()
in Java (so it's not actually a field reference, but a method reference). I could be wrong.
For a definitive word on this, there was this comment by @sbrannen on the AssertJ GitHub repo: assertj/assertj#1418 (comment):
As a general rule of thumb, extensions in JUnit Jupiter should never be stateful.
Instead, they should store state in the ExtensionContext.Store whenever possible in order to allow JUnit to properly scope the state for the current test class, current test method, etc.
This comment was made in the context of the (now deprecated) JUnitJupiterSoftAssertions
, which was also registered programmatically via @RegisterExtension
.
The whole thread serves as a useful example, as the original JUnitJupiterSoftAssertions
extension had a similar issue (state variable) and this issue was where the fix was discussed and implemented. Basically, instead of storing it in an instance variable you put it in the ExtensionContext.Store
object.
from osgi-test.
Here's what I'm talking about:
@RegisterExtension
BundleContextExtension bcExt = new BundleContextExtension();
@RegisterExtension
ServiceUseExtension<Foo> fooUse = new ServiceUseExtension.Builder<>(Foo.class, bcExt) //
.cardinality(0)
.build();
@Test
public void test() throws Exception {
assertThat(fooUse.getService()).isNull();
}
The semantics of this use case according to the docs don't make any sense to need to store the state anywhere by in the instance object.
from osgi-test.
I think you're talking about extensions that can be declared via @ExtendWith(DatabaseExtension.class)
. In that case I'd agree, but we're not able to use that at all since we need to build out the definition of the service and, as far as I'm concerned, specifically want the semantics to be per method. So I fail to see the reasoning behind storing the state elsewhere.
from osgi-test.
I agree that we must use @RegisterExtension
rather than @ExtendWith
. I also agree that it should be per-method semantics.
However, both of these also applied to the AssertJ Jupiter soft assertions extension, and @sbrannen was still concerned about about the extension keeping its own state (as per the issue that I referenced). I don't fully understand the details of why, but I think it had to do with some of the other features of Jupiter around test ordering and test class lifecycles - the specific (failing) use cases are documented here and here. They involve the use of the @TestMethodOrder
annotation and @TestInstance(PER_CLASS)
lifecycle semantics.
The answer they came up with was to use parameter injection to inject the SoftAssertions
object into the test method as a parameter. So the equivalent for your use case would look something like this:
@RegisterExtension
ServiceUseExtension<Foo> fooUseExt = new ServiceUseExtension.Builder<>(Foo.class, bcExt) //
.cardinality(0)
.build();
@Test
public void test(ServiceAware<Foo> fooUse) throws Exception {
assertThat(fooUse.getService()).isNull();
}
...or perhaps as an alternative:
@RegisterExtension
ServiceUseExtension<Foo> fooUseExt = new ServiceUseExtension.Builder<>(Foo.class, bcExt) //
.cardinality(0)
.build();
// Instance injected by fooUseExt at the appropriate time
ServiceAware<Foo> fooUse;
@Test
public void test() throws Exception {
assertThat(fooUse.getService()).isNull();
}
The first implementation would be better if only a couple of your test methods needed the ServiceAware
functionality, and the second implementation would be better if most of your methods needed the ServiceAware
functionality.
Implemented this way, ServiceUseExtension
doesn't even need to extend/implement ServiceAware
.
Also, using the ExtensionContext.Store
, it should be possible for the ServiceUseExtension
to automatically find the BundleContextExtension
without having to explicitly pass it in as a parameter.
I can have a bit of a play with this and submit a PR for your consideration. I'm interested for my own reasons as I'm currently trying to implement an extension of my own and I'm trying to work through and understand these issues (which is how I actually got onto this issue of state in the first place).
I'd also be interested if @sbrannen or someone from the JUnit team could weigh in with a quick word of advice.
from osgi-test.
Related Issues (20)
- [build] Build loop HOT 2
- Exceptions on framework thread are not visible HOT 12
- Does not support JUnit 5's @TestInstance HOT 8
- [junit5] Revisit constructor injection HOT 2
- [assertj] Meta-assertions for bundles HOT 2
- Release 1.1.0 HOT 3
- [junit5] Simplify injector code
- [junit5] InstalledBundleExtension sanity checking
- Do not substitutably import the org.osgi.test.common.annotation package in junit5 HOT 9
- [ServiceExtension] Tweak wildcard type inferencing for upper bounds HOT 6
- [ServiceExtension] Type compatibility check for @InjectService.service() HOT 5
- [InjectingExtension] Refactoring suggestions HOT 10
- Add some descriptive documentation HOT 6
- osgi-test-example-mvn / org.osgi.test.example.player.test.PlayerTest are not executed HOT 4
- Need to obtain code coverage reports and interactive debugging within intellij and gradle plugin HOT 9
- Service instance are kept between different BundleContext's, Tests and test Classes HOT 4
- Provide a Junit5 Extension to start an OSGi-Connect-Framework as part of the test without any need for special setup HOT 4
- @ServiceSource should give a meaningfull error if no services are found HOT 3
- @ServiceSource should support ServiceAware<ServiceType> HOT 4
- readme link to codeql broken HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from osgi-test.