ResourceBundleProvider cannot be injected in a JUnit testing context | Community
Skip to main content
May 28, 2024
Solved

ResourceBundleProvider cannot be injected in a JUnit testing context

  • May 28, 2024
  • 3 replies
  • 1154 views

Greetings,

 

I am injecting a ResourceBundleProvider into a model as shown below.  This works great, but I'm having difficulty writing a JUnit test for this class because I can't find a way to populate the ResourceBundleProvider during test execution.  I am certain the problem is related to the Filter annotation because if I remove it, the test will work (but then the field will be null during live execution).

 

 

// PeopleAggregationImpl.java import javax.inject.Inject; import org.apache.sling.i18n.ResourceBundleProvider; import org.apache.sling.models.annotations.Filter; @Model( adaptables = { Resource.class }, adapters = { PeopleAggregation.class }, resourceType = { PeopleAggregationImpl.RESOURCE_TYPE }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL ) public class PeopleAggregationImpl extends BaseComponentImpl implements PeopleAggregation { @OSGiService private GeographicLocationService geographicLocationService; @586265 @10410875("(component.name=org.apache.sling.i18n.impl.JcrResourceBundleProvider)") private ResourceBundleProvider resourceBundleProvider; private String geoCountryCodes; public String getGeoCountryCodes() { return geoCountryCodes; } @PostConstruct public void init() { Locale languageLocale = ComponentModelUtil.getLocale(resource); geoCountryCodes = getGeoCountryCodesJson(languageLocale); } private String getGeoCountryCodesJson(Locale locale) { JsonArray countryCodeArray = new JsonArray(); if (resourceBundleProvider != null) { final ResourceBundle resourceBundle = resourceBundleProvider.getResourceBundle(locale); I18n i18n = new I18n(resourceBundle); Map<String, String> countryMap = geographicLocationService.getGeoLocationCountryMap(); for(Map.Entry<String, String> entry : countryMap.entrySet()) { JsonObject countryObject = new JsonObject(); countryObject.addProperty("countryCode", entry.getValue().toLowerCase()); countryObject.addProperty("countryName", i18n.get(entry.getKey())); countryCodeArray.add(countryObject); } } return countryCodeArray.toString(); } }

 

 

I've tried many techniques including creating mock ResourceBundleProviders and mock JcrResourceBundleProviders, but nothing has worked.  The example below demonstrates just one of these attempts.

 

 

// PeopleAggregationImplTest.java import org.apache.sling.i18n.ResourceBundleProvider; import org.apache.sling.i18n.impl.JcrResourceBundleProvider; import org.junit.Rule; import io.wcm.testing.mock.aem.junit.AemContext; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import com.tnc.aem.models.PeopleAggregation; @RunWith(MockitoJUnitRunner.class) public class PeopleAggregationImplTest { private static final String RESOURCE_PATH = "/content/page/jcr:content/tab_container/people_aggregation"; private ResourceBundleProvider resourceBundleProvider = Mockito.mock(JcrResourceBundleProvider.class); @Rule public final AemContext ctx = new AemContext(ResourceResolverType.JCR_MOCK); @Before public void setUp() throws Exception { ctx.addModelsForClasses(PeopleAggregationImpl.class); ctx.registerService(ResourceBundleProvider.class, resourceBundleProvider); } public void testPeopleAggregation() throws NoSuchFieldException{ Resource resource = ctx.resourceResolver().getResource(RESOURCE_PATH); PeopleAggregation peopleAggregation = resource.adaptTo(PeopleAggregation.class); }

 

 

Please let me know if you have any ideas how I can populate the ResourceBundleProvider dependency.

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by Umesh_Thakur

I am not sure why are you using 

@filter("(component.name=org.apache.sling.i18n.impl.JcrResourceBundleProvider)")

in your code as it is not recommended to be used. I have seen some developers are using ResourceBundleProvider to get the just locale to work with some translation stuff if this is your requirement then there are many ways to get site locale.

No coming to your context question you can easily get if from slingContext request.

like:

 

@Rule
public SlingContext context = new SlingContext();

@2785667
public void testGetResourceBundleFromRequest() {
ResourceBundle bundle = context.request().getResourceBundle(Locale.CANADA_FRENCH);
assertEquals(Locale.CANADA_FRENCH, bundle.getLocale());
assertNull(((MockResourceBundle) bundle).getBaseName());
}

 

Hope this helps

Umesh Thakur

3 replies

EstebanBustamante
Community Advisor and Adobe Champion
Community Advisor and Adobe Champion
May 28, 2024

Hi


Ideally, you should refactor that sling model, what are you trying to do with the resourceBundleProvider? The @10410875 annotation is not recommended to be used: https://sling.apache.org/documentation/bundles/models.html#discouraged-annotations If you provide more insights we can guide you on the best approach.

 

 

Esteban Bustamante
May 29, 2024

Esteban,

Thank you for the reply.  I have updated the sample code in the original question to more clearly illustrate the use of the ResourceBundleProvider.  I am using the Inject/Filter annotations because, for reasons I do not understand, the @OSGiService annotation does not work for ResourceBundleProvider.  I could alternatively get a resource bundle by adapting this model from a SlingHttpServletRequest, but that seems inappropriate given that this model represents a component resource, not a servlet request.

Umesh_Thakur
Community Advisor
Umesh_ThakurCommunity AdvisorAccepted solution
Community Advisor
May 29, 2024

I am not sure why are you using 

@filter("(component.name=org.apache.sling.i18n.impl.JcrResourceBundleProvider)")

in your code as it is not recommended to be used. I have seen some developers are using ResourceBundleProvider to get the just locale to work with some translation stuff if this is your requirement then there are many ways to get site locale.

No coming to your context question you can easily get if from slingContext request.

like:

 

@Rule
public SlingContext context = new SlingContext();

@2785667
public void testGetResourceBundleFromRequest() {
ResourceBundle bundle = context.request().getResourceBundle(Locale.CANADA_FRENCH);
assertEquals(Locale.CANADA_FRENCH, bundle.getLocale());
assertNull(((MockResourceBundle) bundle).getBaseName());
}

 

Hope this helps

Umesh Thakur

kautuk_sahni
Community Manager
Community Manager
June 4, 2024

@johnagordon83-1 Did you find the suggestions from users helpful? Please let us know if you require more information. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.

Kautuk Sahni