Tags

, , , ,

This post we will mock a method based on parameters passed to method at runtime with a realtime example.

lets say for example, I have a list of user email ids, then i am calling a service to find out list of subscribed and unsubscribed users, so the response from the service will contain two lists, List<String> subscribed and List<String> unsubscribed. The process may contains subscribed to different type of email-service or digest or frequency, or the user interest. once we received the response we can send the current newsletter to users in subscribed list. I also have a constraint in which i can send emails to maximum 5 people.

I’ve mocked the response in a way to test my code like if the total number of characters in Emaild is even then its subscribed, if not its unsubscribed.

    Response generateMockedResponse() {
        Response responseMock = new Response();
        for (String user : getUserEmailDump())
            if (user.length() % 2 != 0)
                responseMock.addToUnSubscribedList(user);
            else
                responseMock.addToSubscribedList(user);
        return responseMock;
    }

It sent only mail to right users (users name have chars of even length). and considering limit here as 5, the following test failed. Service sending mail may fail for some user.


    @Test
    public void WrongTestForValidation_shouldOnlySendMaximumNewsletter() {
        when(serviceSpy.filter((Request) Matchers.any(Request.class))).thenReturn(utility.generateMockedResponse(Utility.getUserEmailDump()));

        Response response = utility.generateMockedResponse(Utility.getUserEmailDump());
        response.setTotalSuccessFullRecipients(response.getSubscribedUsers().size());
        when(serviceSpy.sendNewsletter((Request) Matchers.any(Request.class))).thenReturn(response);

        int totalNewslettersSent = sender.send(serviceSpy, utility.getUserEmailDump());
        assertFalse(&amp;quot;Request should not exceed maximum limit&amp;quot;, totalNewslettersSent &amp;gt; MAX_LIMIT_PER_REQUEST);
    }

Because its is returning more than Maximum_Limit which is not possible at all Since we have handle it in code and sending sublist only.

    //NewsletterSender Logic
    if (subscribedUsers.size() &amp;gt; MAX_LIMIT_PER_REQUEST) {
        System.out.println(&amp;quot;Sending newsletter for &amp;quot; + MAX_LIMIT_PER_REQUEST + &amp;quot; subscribed users&amp;quot;);
        Request newsletterSendRequest = new Request(subscribedUsers.subList(0, MAX_LIMIT_PER_REQUEST));
        response = service.sendNewsletter(newsletterSendRequest);
    }

Eventhought it says “Sending newsletter for 5 subscribed users” in console as it’s handled accordingly, the response is an issue. Beacuse while mocking returning the response as same as total subscribers available, which i have generated is wrong.

The issue is its not dynamic mocking. Its mocking the data, but its using static data, its not based on the new request which. The mock should consider the list (dynamically, i.e the sublist which comes in request and filling the successfulRecipients accordingly)

This made me realize the value of ThenAnswer in mock.

when(serviceSpy.sendNewsletter((Request) Matchers.any(Request.class))).thenAnswer(new Answer&amp;lt;Object&amp;gt;() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                Request request = (Request) invocation.getArguments()[0];
                //whatever condition that makes sending fail
                Iterator&amp;lt;String&amp;gt; subscriberList = request.getEmailList().iterator();
                int sentCount = 0;
                while (subscriberList.hasNext()) {
                    String user = subscriberList.next();
                    if (!user.matches(&amp;quot;.*\\d+.*&amp;quot;)) {
                        sentCount++;
                    } else {
                        System.out.println(&amp;quot;super this is removed&amp;quot; + user);
                    }
                }
                Response response = new Response();
                response.setTotalSuccessFullRecipients(sentCount);
                return response;
            }
        });    

In development or Testing, we don’t use the real services and we prefer mocks / stubs. because the of the cost per service request, or in order to reduce the test time, or the real service might not be available.

Have a look at full code in my git repository : Playing-With-Unit-Test

 

Advertisements