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;
@inject
@filter("(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.
Solved! Go to Solution.
Views
Replies
Total Likes
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();
@test
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
Hi
Ideally, you should refactor that sling model, what are you trying to do with the resourceBundleProvider? The @filter 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,
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.
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();
@test
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
@johnagordon83 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.
Views
Replies
Total Likes
Views
Likes
Replies
Views
Likes
Replies