0

I am writing a test case for "headersection()" method. Inside this method, it is calling a constructor of another class, let's say "InformationHeader.java" class. Inside this constructor, it will invoke one method called as "makepage()". Again "makepage()" method will invoke another "createpage()" method.

I wanted to skip the method call to "createpage()" in my test case. Please suggest how to achieve this scenario?

private void headersection(Object child) {
    headerobject = new InformationHeader(parameter_1, parameter_2, parameter_3, parameter_4);
    //lines of code
}


//InformationHeader.java
public InformationHeader(parameter_1, parameter_2, parameter_3, parameter_4) {
    //lines of code
    makepage();
    //lines of code
}

public final void makepage() { 
    //lines of code
    createpage();    //I wanted to skip this method call 
}

Any help would be appreciated

Thanks

Armine
  • 1,675
  • 2
  • 24
  • 40
  • 3
    It's simple, without modifying bytecode for tests, you can't. But also it seems a bit strange that you want to test a `private` method. Your tests should only test the API of a class (e.g. only it's public members) – Lino Jan 09 '20 at 10:52
  • @Lino says Reinstate Monica, We can test private methods using Reflection. Thanks for your suggestion. – Kinjal Rathod Jan 09 '20 at 11:10
  • You could change your method a bit. Write a method which create the InformationHeader class, this method can be mocked. –  Jan 10 '20 at 08:48
  • @Matthias Lauber, Thank You for your suggestion. Can you please tell me how to mock that method which create "InformationHeader" class. And "public InformationHeader" is constructor in InformationHeader.java not a method. Please share your thoughts. – Kinjal Rathod Jan 10 '20 at 09:02
  • do you want to unit test your method, or is it more an integration test? –  Jan 10 '20 at 09:57

2 Answers2

0

I hope I got your question, but as I mentioned in my comment, you could change the method a bit and create a method which could be mocked.

void headersection(Object child) {
    headerobject = getInformationHeader(/*parameter*/)
    //lines of code
}

InformationHeader getInformationHeader(/*parameter*/) {
    return new InformationHeader(parameter_1,parameter_2,parameter_3,parameter_4);
}

I don't know your class name in which the headersection mehtod is stored, lets say SectionService. Now, you could use Mockito to create a so called spy

@InjectMock
SectionService serviceToTest; 
SectionService spyServiceToTest = Mockito.spy(serviceToTest);
InformationHeader spyInformationHeader = Mockit.spy(new InformationHeader(/*parameter*/));

Now you can mock a call inside of the tested class:

Mockito.doReturn(spyInformationHeader).when(spyServiceToTest).getInformationHeader(//parameter);
Mockiot.doNothing().when(spyInformationHeader).createpage(); 

Here is a stackoverflow question which is dealing with spy calls and here is the Mockito documentation.

I hope this helps, greetings Matthias

Armine
  • 1,675
  • 2
  • 24
  • 40
0

The answer using spies doesn't work. The new InformationHeader(/*parameter*/) will call createpage. You will have the same problem with EasyMock.

The problem is that you can't mock a method before creating a partial mock. So when the constructor is calling a method, it doesn't work.

I would probably rethink my design if I was you. But not having the full picture, I can't give advice on that.

Keeping the current design, the easiest is actually to do a manual mock. It goes like this.

public class MyTest extends EasyMockSupport {

    @Test
    public void test() {
        InformationHeader header = new InformationHeader("a", "b", "c", "d") {
            @Override
            public void createpage() {
                // do nothing
            }
        };
        ToTest toTest = partialMockBuilder(ToTest.class)
                .withConstructor()
                .addMockedMethod("createHeader")
                .mock();
        expect(toTest.createHeader()).andReturn(header);

        replayAll();

        toTest.headersection(null);
    }
}

class ToTest {
    void headersection(Object child) {
        InformationHeader headerobject = createHeader();
    }

    InformationHeader createHeader() {
        return new InformationHeader("a", "b", "c", "d");
    }
}

class InformationHeader {

    public InformationHeader(String p1, String p2, String p3, String p4) {
        makepage();
    }

    public final void makepage() {
        createpage();
    }

    public void createpage() {
        throw new RuntimeException("Should not be called");
    }
}
Henri
  • 5,551
  • 1
  • 22
  • 29
  • Thank You for suggestion. Seems like as per your answer code base is modified. But I cannot refactor the code. However, I will give a try to your solution. Thanks. – Kinjal Rathod Jan 13 '20 at 05:22
  • If you really can't refactor anything (which is never the case), PowerMock can help you mocking the `new InformationHeader` call. – Henri Jan 14 '20 at 19:03
  • Thank You Henri, but I am forced to use "EasyMock" framwork only. – Kinjal Rathod Jan 16 '20 at 07:37