The validation method is called in the constructor.

I have a constructor that calls a method, for example:

public Foo(boolean runExtraStuff) {
    if (runExtraStuff){
        doExtraStuff();
    }
}

The method doExtraStuff()runs some additional commands that are not easy to scoff at (things like checking the database to initialize some variables). It might be better for the designer not to do this, but this is the code that I have to work with at the moment.

I would like to create a unit test to make sure that doExtraStuff()is called when boolean runExtraStuffis true and does not start when the boolean is false. I am using JMockit.

However, I am not sure how to do this. Normally I would use Verificationson the mocked object, but since I am testing the constructor, I cannot use this object. So, how can I check if a method is called inside the constructor?

+4
source share
2 answers

This is easy enough, even if it requires partial mockery:

@Test
public void runsSetupWhenRequestedOnFooInitialization()
{
    // Partially mocks the class under test:
    new Expectations(Foo.class) {};

    final Foo foo = new Foo(true);

    // Assuming "setup" is not private (if it is, use Deencapsulation.invoke):
    new Verifications() {{ foo.setup(); }};
}

@Test
public void doesNotRunSetupWhenNotRequestedOnFooInitialization()
{
    new Expectations(Foo.class) {};

    final Foo foo = new Foo(false);

    new Verifications() {{ foo.setup(); times = 0; }};
}

Of course, it would be better to avoid ridicule in such a case; instead, the test should check the state of the object through getters or other available methods, if at all possible.

+3
source

Well, the simple answer does not use JMockit at all.

in src / main / java / example ..

package example;

public class Foo {
    private boolean setupRan = false;

    public Foo(boolean runSetup) {
        if (runSetup) setup();
    }

    public void setup() {
        setupRan = true;
    }

    public boolean getSetupRan() {
        return setupRan;
    }
}

in src / test / java / example ..

package example;

import static org.assertj.core.api.Assertions.*;

import org.junit.Test;

public class FooTest {

    private Foo testSubject;

    @Test
    public void should_run_setup() {
        testSubject = new Foo(true);
        assertThat(testSubject.getSetupRan()).isTrue();
    }

    @Test
    public void should_not_run_setup() {
        testSubject = new Foo(false);
        assertThat(testSubject.getSetupRan()).isFalse();
    }

}

I will go out on a limb and guess that you are interested in a partial layout:

in src / main / java / example ..

package example;

public class Foo1 {
    public Foo1(boolean runSetup) {
        if (runSetup) setup();
    }

    public void setup() {
        System.out.println("in setup()");
    }
}

in src / test / java / example ..

package example;

import static org.assertj.core.api.Assertions.*;

import mockit.Expectations;
import mockit.Mocked;
import org.junit.Test;

public class Foo1Test {

    // hateful partial mocking of test subject!
    @Mocked({"setup()"})
    private Foo1 testSubject;

    @Test
    public void should_run_setup() {
        new Expectations() {{
            testSubject.setup(); // setup() is called
        }};
        testSubject = new Foo1(true);
    }

    @Test
    public void should_not_run_setup() {
        new Expectations() {{
            testSubject.setup(); times = 0;
        }};
        testSubject = new Foo1(false);
    }
}

1: , println, .
EDIT 2: testSubject.setup() times = 0

+1

All Articles