Expand my Community achievements bar.

Enhance your AEM Assets & Boost Your Development: [AEM Gems | June 19, 2024] Improving the Developer Experience with New APIs and Events

junits for tagmanager is getting null

Avatar

Level 6

Hi Team,

I'm getting nullpointer exception for tagmanager in jnuits,

    private final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);

    @Mock
    private TagManager tagManager;
   
@Mock
   Tag tag;
aemContext.registerAdapter(ResourceResolver.class, TagManager.class, tagManager);
 Mockito.lenient().when(tagManager.resolve("tag:/tag1")).thenReturn(tag);
 
Any suggestions for this will be helpful,
Thanks in advance.
9 Replies

Avatar

Level 6

I'm gettign below exception

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class [Lcom.day.cq.tagging.Tag;
Mockito cannot mock/spy because :
 - VM does not support modification of given type

Avatar

Level 7

Hi @Keerthi0555 ,

You can try the below snippet

private final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);

@Mock
private TagManager tagManager;

@Mock
private Tag tag;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
    Mockito.lenient().when(aemContext.resourceResolver().adaptTo(TagManager.class)).thenReturn(tagManager);
    Mockito.lenient().when(tagManager.resolve("tag:/tag1")).thenReturn(tag);
}

@Test
public void testYourMethod() {
    // Your test logic here
}

Make sure to initialize your mocks using MockitoAnnotations.initMocks(this); and properly set up the AemContext. This should resolve the null pointer exception.

Thanks,
Madhur

Avatar

Level 7

If this doesn't work you can try to register the  TagManager with AEM context.

Here is the code for that

import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit5.AemContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import javax.jcr.RepositoryException;
import javax.jcr.Session;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class YourTestClass {

    private final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);

    @Mock
    private TagManager tagManager;

    @Mock
    private Tag tag;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.initMocks(this);
        // Register the TagManager mock with AemContext
        aemContext.registerAdapter(ResourceResolver.class, TagManager.class, tagManager);
    }

    @test
    void testResolveTag() throws RepositoryException {
        // Define the behavior of the mock
        Mockito.lenient().when(tagManager.resolve("tag:/tag1")).thenReturn(tag);

        // Your test logic here
        Tag resolvedTag = tagManager.resolve("tag:/tag1");

        // Assert that the resolved tag is the same as the mocked tag
        assertEquals(tag, resolvedTag);
    }
}

Avatar

Level 6

Hi Madhur,

 

Thank you, but it's throwing below error

org.mockito.exceptions.base.MockitoException:
Failed to release mocks

This should not happen unless you are using a third-part mock maker

Caused by: org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class [Lcom.day.cq.tagging.Tag;
Mockito cannot mock/spy because :
- VM does not support modification of given type
... 70 more

Avatar

Level 9

Hi @Keerthi0555 ,

It seems like you're trying to mock the TagManager and Tag objects in your JUnit tests, but you're encountering a NullPointerException when trying to use the mocked TagManager.

Here are a few things to check and adjust in your test setup:

  1. Initialization Order: Ensure that you're initializing the mocks properly and in the correct order. Mockito mocks need to be initialized before they're used.

  2. ResourceResolver Mock: The ResourceResolverType.JCR_MOCK used in your AemContext initialization suggests that you're using a mocked JCR environment. Make sure that the mock is set up correctly and that it includes the necessary components for the TagManager to function.

  3. Mockito Annotations: You've used @Mock annotations for TagManager and Tag, which is good. Just ensure that these annotations are properly integrated with your test framework and that the Mockito runner or rule is correctly applied.

  4. Adapter Registration: The way you're registering the adapter for ResourceResolver to TagManager looks correct. However, ensure that this registration is taking effect and that the adapter is being correctly resolved within your test scenario.

Here's an adjusted version of your test setup with some comments:

 

@RunWith(MockitoJUnitRunner.class) // Make sure you're using the Mockito runner or rule
public class YourTest {

    // Initialize the AemContext
    private final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);

    @Mock
    private TagManager tagManager;
    
    @Mock
    private Tag tag;

    @Before
    public void setUp() throws Exception {
        // Register the TagManager adapter
        aemContext.registerAdapter(ResourceResolver.class, TagManager.class, tagManager);
    }

    @Test
    public void testYourMethod() {
        // Mock behavior of tagManager
        Mockito.when(tagManager.resolve("tag:/tag1")).thenReturn(tag);
        
        // Perform your test scenario
        // Ensure that the tagManager is being used correctly in your tested method
        // Assert expected behavior based on the mocked tagManager response
    }
}

 

Make sure that your test scenario properly exercises the code that uses the TagManager and handles its responses accordingly. If you're still encountering NullPointerExceptions, double-check your initialization steps and ensure that all necessary dependencies are properly mocked and registered within your test environment.

Avatar

Community Advisor

Hi,

Your code seems ok, it sounds to me that the issue is because of Mockito and Java incompatibility versions, can you check this thread: https://stackoverflow.com/questions/41050029/mockito-cannot-mock-this-class Also share which dependencies you are using.

 

Hope this helps.



Esteban Bustamante

Avatar

Community Advisor

I got a code snippet laying around that you can try:

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

import com.day.cq.tagging.Tag;
import com.day.cq.tagging.TagManager;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(AemContextExtension.class)
@ExtendWith(MockitoExtension.class)
public class PageTagsTest {

    private final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);

    @Mock
    private TagManager tagManager;

    @Mock
    private Tag tag;

    @BeforeEach
    public void setUp() {
        // Register TagManager with AemContext
        aemContext.registerAdapter(ResourceResolver.class, TagManager.class, tagManager);

        // Mock the TagManager behavior
        when(tagManager.resolve("tag:/tag1")).thenReturn(tag);
        when(tag.getTagID()).thenReturn("tag:/tag1");

        // Create a test page with cq:tags
        aemContext.create().page("/content/sample");
        aemContext.create().resource("/content/sample/jcr:content", "cq:tags", new String[]{"tag:/tag1"});
    }

    @test
    public void testPageTags() {
        // Get the page
        PageManager pageManager = aemContext.pageManager();
        Page page = pageManager.getPage("/content/sample");

        assertNotNull(page, "Page should not be null");
        assertEquals("/content/sample", page.getPath());

        // Retrieve the tags
        Tag[] tags = page.getTags();
        assertNotNull(tags, "Tags should not be null");
        assertEquals(1, tags.length);
        assertEquals("tag:/tag1", tags[0].getTagID());
    }
}

Avatar

Administrator

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



Kautuk Sahni