0

I have a method on which I'd like to run a JUnit test. I'm mocking the cq5 page using JMockit.

My test method looks like this

@Mocked
Page page;
@Mocked
PageManager pageManager;
Tag testTag = pageManager.createTag("someID","someTitle","someDescription");//i've left out the try catch for brevety
System.out.println(testTag.getTitle()); // always null here


public void testSomeMethod() {

    new Expectations() {
        // variables declared here are mocked by default
        {
            page.getProperties();
            propertyMap.put("cq:tags", testTag);
            returns(new ValueMapDecorator(propertyMap));
        }
    };
    String propertyValue = methodToBeTested(page);
    Assert.assertEquals(propertyValue, "someTitle");
}

And the actual method to be tested does this :-

public static String getTopic(Page page) {

    String topic = null;
    Tag[] tags = page.getTags();
    System.out.println(tags.size()); // returns 0 when I run the test.
    for (int i = 0; i < tags.length; i++) {
        Tag tag = tags[i];

            topic = tag.getTitle();
        }
    }
    return topic;

}

This always returns null when I run the test; however the method to be tested works correctly in the real scenario.

I suspect I'm not setting/mocking PageManager correctly, and consequently, my testTag is null

How do I mock this correctly to get the output I'm looking for?

bongman1612
  • 440
  • 1
  • 11
  • 23
  • 1
    The tested method calls `page.getTags()`, but no expectation was recorded for it; instead, the test records `page.getProperties()`, which is never called from the `getTopic(Page)` method; so, that's why it returns null, ie, the test is not consistent with what the method it tests is doing. – Rogério May 08 '15 at 21:37
  • You could also try using [wcm.io Testing](http://wcm.io/testing/aem-mock/). I know it allows you to load JSON files and use them as content to mock AEM `Page` instances. I haven't tried it with tags though. – toniedzwiedz Jun 11 '15 at 16:51
  • see my answer here: https://forums.adobe.com/thread/2536290 on why you are getting empty array for Page#getTags – Ahmed Musallam Feb 04 '19 at 16:31

3 Answers3

2

You're getting to this testing from the wrong side. The way mocks (usually - I've never worked with jmockit specifically) work is, you create a blank object that acts as an impostor. This impostor is not a true PageManager - it only acts as one, and introduces himself as one whenever asked. When someone asks that impostor to do something (like calling it's method), the impostor does not know what to do, so it does nothing and returns null. However, you can tell the impostor how to behave in certain situations. Namely, you can tell it what to do when a method is called.

In your case, you don't need to create actual tags to test that method - you only need to mock a page object that, when asked for it's tags, will return an array containing a mocked tag which, in turn, when asked for it's title, will respond with the title you actually want to use in your test.

I don't know jmockit, so I cannot provide any code snippet. This, however, is a general question not strictly connected to CQ5/AEM

CptBartender
  • 1,235
  • 8
  • 22
0

You may not be able to find any 'setter' methods for all objects you are trying to mock and this is anyways not the correct approach to mock.

The best way as mentioned by is to use mocked pages. You can use the Expectations class (mockit.Expectations) to mock the values to be returned by certain methods in the object.

See this example of mocking a 'SlingHttpServletRequest' object in a MockedClass class.

@Test
    public void testMethod(@Mocked final SlingHttpServletRequest request){
        String indicator ;
        new Expectations() {
            {
                request.getParameter("archive");
                returns("true");
            }
        };

        indicator = OriginalClass.originalMethod(request);
        Assert.assertEquals(indicator, "true");
    }

In a similar way, you can mock other objects and their desired values.

Riju Mahna
  • 6,718
  • 12
  • 52
  • 91
0

I have answered the same question here: https://forums.adobe.com/thread/2536290

I ran into the same issue. in order to resolve Tags, they must exists under /content/cq:tags/your/tag or /etc/tags (legacy).

The Page#getTags implementation makes a call to TagManager#getTags which in turn tries to resolve the actual tag resource in the repo. Since you are testing in an AEM context, you have to load these tags in the appropriate location for the MockTagManager to resolve them.

What this means is that you need to load your tags into the AEM test context just like you've loaded your resources (via json).

Take a look at the aem-mock TagManager impl here: wcm-io-testing/MockTagManager.java at develop · wcm-io/wcm-io-testing · GitHub start with the resolve method and debug your way to figure out where you need to add those tags.

Ahmed Musallam
  • 9,523
  • 4
  • 27
  • 47