### Question:
FeaturableModel extends FeaturableAbstract { @Override public final void addFeature(Feature feature) { try { super.addFeature(feature); } catch (final LionEngineException exception) { throw new LionEngineException(exception, media, exception.getMessage()); } } FeaturableModel(Services services, Setup setup); @Override final void addFeature(Feature feature); @Override Media getMedia();  }### Answer:
@Test void testFeaturableCompatible() { final Featurable featurable = new FeaturableModel(services, setup); final MyFeatureInterface feature = new MyFeature(services, setup); featurable.addFeature(feature); assertTrue(featurable.hasFeature(MyFeatureInterface.class)); assertTrue(featurable.hasFeature(MyFeature.class)); assertEquals(feature, featurable.getFeature(MyFeature.class)); for (final Feature current : featurable.getFeatures()) { assertTrue(feature.getClass().equals(current.getClass()) || Identifiable.class.isAssignableFrom(current.getClass()) || Recycler.class.isAssignableFrom(current.getClass()), current.getClass().getName()); } for (final Class<? extends Feature> type : featurable.getFeaturesType()) { assertTrue(MyFeatureInterface.class.isAssignableFrom(type) || Identifiable.class.isAssignableFrom(type) || Recycler.class.isAssignableFrom(type), type.getName()); } }
@Test void testFeaturableNotcompatible() { final Featurable featurable = new FeaturableModel(services, setup); final MyFeatureNotCompatible feature = new MyFeatureNotCompatible(services, setup); featurable.addFeature(feature); assertTrue(featurable.hasFeature(MyFeatureNotCompatible.class)); assertEquals(feature, featurable.getFeature(MyFeatureNotCompatible.class)); for (final Feature current : featurable.getFeatures()) { assertTrue(feature.getClass().equals(current.getClass()) || Identifiable.class.isAssignableFrom(current.getClass()) || Recycler.class.isAssignableFrom(current.getClass()), current.getClass().getName()); } for (final Class<? extends Feature> type : featurable.getFeaturesType()) { assertTrue(MyFeatureNotCompatible.class.isAssignableFrom(type) || Identifiable.class.isAssignableFrom(type) || Recycler.class.isAssignableFrom(type), type.getName()); } }
@Test void testFeatureAnnotation() { final Featurable featurable = new FeaturableModel(services, setup); final MyFeatureInterface featureModel = new MyFeature(services, setup); featurable.addFeature(featureModel); final MyFeatureModel feature = featurable.addFeatureAndGet(new MyFeatureModel(services, setup)); assertEquals(featureModel, feature.feature); }
@Test void testFeatureAnnotationNotFound() { final Featurable featurable = new FeaturableModel(services, setup); final AtomicReference<String> unfilledType = new AtomicReference<>(); final Feature feature = new FeatureModel(services, setup) { private @FeatureGet String type; @Override public void prepare(FeatureProvider provider) { super.prepare(provider); unfilledType.set(type); } }; assertThrows(() -> featurable.addFeature(feature), "[transformable_FeaturableModelTest.xml] Class not found: " + String.class + " in " + feature); }