cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

How to instantiate CanonicalItem for writing junit test cases for composition handlers.

Former Member
0 Likes
285

Hi Experts,

We have a requirement for writing Junit test for Composition Handlers in Datahub.
For that we will need to create a real object for CanonicalItem as we have to return the CanonicalItem after setting the field (requirement for both Localized and non Localized fields).

I found the TestCanonicalProduct which extends the CanonicalItem and tried to use it. Still I was not able to set the Field as
BaseDataItem.setField(String fieldName, Object value) fails at

Optional dataItemAttribute = this.getAttributeDefinition(fieldName);

I have also tried to use the direct CanonicalItem instantiate(String type) but not successful.

Could anybody please help to resolved this issue.

Regards,

Accepted Solutions (0)

Answers (1)

Answers (1)

Slava
Product and Topic Expert
Product and Topic Expert
0 Likes

Jeophry,

it's not easy to use real objects in unit tests. Mocking and verifying calls on the mocks is probably the simplest solution, e.g.

 final CanonicalItem item = Mockito.mock(CanonicalItem.class);
 ....
 Mockito.verify(item).setField("name", value);

Real canonical items use static methods/members for caching valid attributes and canonical types. That significantly complicates usage of real canonical items in tests. However, it's possible with some help from the datahub SDK.

To create an instance you can use CanonicalItemBuilder, which is distributed with the SDK in datahub-test-api. That builder creates a real CanonicalItem, e.g.

 CanonicalItem item = CanonicalItemBuilder.forType(CanonicalType.PRODUCT).build();

or

 CanonicalItem item = CanonicalItemBuilder.forType("MyCustomType").build();

Another challenge is to deal with those cached metadata. You can use MetadataContext and BaseMetadataUnitTest classes also available in datahub-test-api.

When put together you test may look something like this:

 public class LocalizedCompositionRuleHandlerUnitTest extends BaseMetadataUnitTest
 {
     private static final String LOCALIZED_ATTRIBUTE = "localizedAttribute";
 
     private final LocalizedCompositionRuleHandler handler = new LocalizedCompositionRuleHandler();
     private CanonicalItem canonicalItem;
     private MetadataContext metadataContext;
 
     @Before
     public void setUp()
     {
         metadataContext = new MetadataContext()
                 .forRawType(RawType.PRODUCT.getTypeCode())
                 .forCanonicalType(CanonicalType.PRODUCT.getTypeCode());
         canonicalItem = CanonicalItemBuilder.forType(CanonicalType.PRODUCT).build();
 
         handler.setTransformationExpressionProcessor(BaseDataItem::getField);
     }
 
     @Test
     public void testIsApplicableForLocalizedAttribute()
     {
         // metadataContext offers more methods for basic and collection attributes too
         final CanonicalAttributeDefinition attrDef = metadataContext.defineAndMapLocalizedAttribute(LOCALIZED_ATTRIBUTE, LOCALIZED_ATTRIBUTE, "name");
 
         Assert.assertTrue(handler.isApplicable(attrDef));
     }
     ...
     @Test
     public void testComposeWithDifferentRawAndCanonicalAttributeNames()
     {
         final CanonicalAttributeDefinition attrDef = metadataContext.defineAndMapLocalizedAttribute("name", "baseName");
         final List<RawItem> items = Arrays.asList(
                 rawProduct().withField("baseName", "jacket").withIsoCode("en").build(),
                 rawProduct().withField("baseName", "jacke").withIsoCode("de").build());
 
         final CompositionGroup<RawItem> group = new CompositionGroup<>(items, Arrays.asList(attrDef), null);
         handler.compose(attrDef, group, canonicalItem);
 
         assertEquals("jacke", canonicalItem.getField("name", Locale.GERMAN));
         assertEquals("jacket", canonicalItem.getField("name", Locale.ENGLISH));
     }
 
     private RawItemBuilder<RawItem> rawProduct()
     {
         return RawItemBuilder.forType(RawType.PRODUCT);
     }

Hope this helps.

Former Member
0 Likes

Hi

we are getting NullPointerException @ .forCanonicalType(CanonicalType.PRODUCT.getTypeCode());

For this, where can we set the value of the typecode

Thanks and regards,

Slava
Product and Topic Expert
Product and Topic Expert
0 Likes

Jeophry,

could you paste the stack trace here? If your test class is not too large, pasting your unit test would help too.

Slava

bidyadhar_tripathy
Participant
0 Likes

Hi Jeophry,

I am also getting the same error. Were you able to solve your junit issue ? if yes could you please help me on this.