-1

For testing my DedupServiceWrapperImpl class I need to mock to private method "isDedupEnabled" and "isNew". this is the class under the test:

public class DedupServiceWrapperImpl implements DedupServiceWrapper {

    @Inject
    private DedupService dedupService;

    @Inject
    private EventTypeService eventTypeService;

    @Inject
    private MessageLogService messageLogService;

    private static final Logger logger = LoggerFactory.getLogger(DedupServiceWrapperImpl.class);

public Message dedup(Message message) {
   if (isDedupEnabled(eventTypeName)) {
     System.out.println("Dedup is enabled.");
     if (isNew(digest)) {
         System.out.println("it is new");
     } else {
        System.out.println("is not new");
     }
   } else {
       System.out.println("Dedup is not Enabled");
   }
}

private boolean isNew(Digest digest) {
        return !dedupService.checkIfExists(digest.getDigest());
    }

    private boolean isDedupEnabled(String eventTypeName) {
        boolean result = false;
        try {
            logger.info("Fetching eventType:{} to see if dedup is enabled on it.", eventTypeName);
            EventType eventType = eventTypeService.findByName(eventTypeName);
            if (eventType.isDedupEnabled()) {
                result = true;
            }
        } catch (NotFoundException nfe) {
            logger.warn("EventType '{}' not found!", eventTypeName);
        }
        return result;
    }
}

And here is my unit test class:

import com.sun.org.apache.bcel.internal.classfile.Method;
import com.tosan.chapar.core.exception.NotFoundException;
import com.tosan.chapar.core.service.DedupService;
import com.tosan.chapar.core.service.MessageLogService;
import com.tosan.chapar.ivr.service.DedupServiceWrapper;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.messaging.MessageHeaders;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
//import org.junit.Test;
import org.springframework.messaging.Message;

import static org.junit.runner.Request.method;
import static org.mockito.Mockito.*;
import static org.testng.Assert.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest(DedupServiceWrapperImpl.class)
public class DedupServiceWrapperImpl_DedupUTest {

    private static final String payload = "Hello UTest.";
    private Message inputMessage;
    private MessageHeaders messageHeaders;
    //@Mock
    //private DedupService dedupService;
    //@InjectMocks
    private DedupServiceWrapper dedupServiceWrapper;

    @Test
    public void testName() throws Exception {

    }

    @SuppressWarnings("unchecked")
    @BeforeMethod
    public void setupMocks() throws NotFoundException {
        MessageLogService messageLogService = mock(MessageLogService.class);
        /*digest = mock(Digest.class);
        eventType = mock(EventType.class);
        eventType.setName("modern_chaparbo_free");
        eventType.setDedupEnabled(true);

        eventTypeService = mock(EventTypeServiceImpl.class);
        when(eventTypeService.findByName("modern_chaparbo_free")).thenReturn(eventType);*/

        messageHeaders = mock(MessageHeaders.class);
        when(messageHeaders.get("eventTypeName")).thenReturn("modern_chaparbo_free");
        when(messageHeaders.get("recipient")).thenReturn("+982112345678");
        when(messageHeaders.size()).thenReturn(2);

        inputMessage = mock(Message.class);
        when(inputMessage.getHeaders()).thenReturn(messageHeaders);
        when(inputMessage.getPayload()).thenReturn(payload);
    }

    /**
     * dedupEnabled is false
     */
    @Test//(expected = RuntimeException.class)
    public void dedup_Disablededup_dedupeIsNotDone()  throws Exception{
        //doNothing().when(cmd).dnsCheck(HOST, any(InetAddressFactory.class))
        DedupServiceWrapperImpl spy = PowerMockito.spy(new DedupServiceWrapperImpl());
        //DedupServiceWrapper spy = mock(DedupServiceWrapperImpl.class);
        PowerMockito.doReturn(false).when(spy, "isDedupEnabled", anyString(),);
        //PowerMockito.verifyPrivate(spy, times(0)).invoke("isDedupEnabled", anyString());
        //PowerMockito.when(spy, method(DedupServiceWrapperImpl.class, "isDedupEnabled", String.class)).withArguments(anyString()).thenReturn(false);
        //PowerMockito.verifyPrivate(spy, times(2)).invoke("isDedupEnabled", anyString());
        //PowerMockito.doReturn(false).when(spy, method(DedupServiceWrapperImpl.class, "isDedupEnabled", String.class)).withArguments(anyString());
        /*DedupServiceWrapper truck = new DedupServiceWrapperImpl();
        DedupServiceWrapper truckSpy = PowerMockito.spy(truck);
        PowerMockito.doReturn(false).when(truckSpy,
                "isDedupEnabled");*/
        Message message = spy.dedup(inputMessage);
        org.junit.Assert.assertEquals(inputMessage, message);
        assertNotNull(message);
        assertEquals(message, inputMessage);
    }


}

I have tried all samples in my test class, but they do not work and I make them comment...

I can not mock tow private methods - how can I do this? why does not it work?

It throws this:

Method threw 'org.mockito.exceptions.misusing.WrongTypeOfReturnValue' exception. Cannot evaluate com.tosan.chapar.ivr.service.impl.DedupServiceWrapperImpl$$EnhancerByMockitoWithCGLIB$$9a511df1.toString()
juherr
  • 5,640
  • 1
  • 21
  • 63
m.mjn202
  • 43
  • 1
  • 9
  • Why would you want to mock a private method? The only things that can call it are other methods **inside your mock object**. – Oliver Charlesworth Apr 08 '17 at 11:50
  • It's unclear why you are doing this. Unit tests requires mocking the dependencies then calling a method on the CUT. You then verify that the CUT behaves in the right way - calls the right methods on the dependencies, returns the right value given what you have stubbed. There should be no reason to mock a `private` method _inside_ the CUT! – Boris the Spider Apr 08 '17 at 11:53
  • I want to test "dedup(Message message)" method which calls "isDedupEnabled" and "isNew" that are private methods. I want to mock these private methods. – m.mjn202 Apr 08 '17 at 11:54
  • Despite this sounding like bad practice (private methods are an implementation detail), I'm not even sure that's possible - you want to mock the object you're testing? – Oliver Charlesworth Apr 08 '17 at 11:55
  • @m.mjn202 no, you really don't want to mock private methods. `isDedupEnabled`, for example, calls `eventTypeService.findByName(eventTypeName)` - so you **stub** `eventTypeService.findByName` to provide the right value to that call given what you are testing. – Boris the Spider Apr 08 '17 at 11:56
  • @Boris the Spider, Thank you. I have used your way. but "eventTypeService.findByName..." throw "NullpointException". I have used Mock and InjectMock annotations to inject EventTypeService to CUT, but it does not work): – m.mjn202 Apr 08 '17 at 12:15

2 Answers2

1

One can mock private methods using PowerMock, or you could look into using Mockito spies for partial mocking.

But most often, the need for such tricks is a deficient design under test. In other words: instead trying to fix the symptoms of hard-to-test production code... Rather spend your time on making your code easy to test.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
0

You mixed TestNG (org.testng.annotations.*) and JUnit (org.junit.runner.*) in the same class which is not allowed.

If you want to use PowerMock and TestNG, you need to extend PowerMockTestCase. Check the documentation: https://github.com/powermock/powermock/wiki/TestNG_usage

juherr
  • 5,640
  • 1
  • 21
  • 63