Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the differences between @Mocked, @Injectable, and @Capturing?

First, I define a class, let's say Robot.

public class Robot {

    private Vision vision;

    public Object recognizeObject(List<List<Integer>> frames) {
        vision = new Vision();
        return vision.recognize(frames);
    }
}

Class of Robot has several dependencies, one of them is Vision.

public class Vision {

    public Object recognize(List<List<Integer>> frames) {
        // do magic stuff, but return dummy stuff
        return null;
    }

}

Then in the test class, I simply test the invocation of recognize().

@RunWith(JMockit.class)
public class RobotTest {

    @Test
    public void recognizeObjectWithMocked(@Mocked final Vision vision) {
        List<List<Integer>> frames = new ArrayList<>();
        vision.recognize(frames);

        new Verifications() {{
            vision.recognize((List<List<Integer>>) any);
            times = 1;
        }};
    }

    @Test
    public void recognizeObjectWithInjectable(@Injectable final Vision vision) {
        List<List<Integer>> frames = new ArrayList<>();
        vision.recognize(frames);

        new Verifications() {{
            vision.recognize((List<List<Integer>>) any);
            times = 1;
        }};
    }

    @Test
    public void recognizeObjectWithCapturing(@Capturing final Vision vision) {
        List<List<Integer>> frames = new ArrayList<>();
        vision.recognize(frames);

        new Verifications() {{
            vision.recognize((List<List<Integer>>) any);
            times = 1;
        }};
    }
}

Based on these tests, I think that @Mocked, @Injectable, and @Capturing can be used interchangeably.

  • Is that correct?

  • If the answer is no, then is there any case that only @Mocked/@Injectable/@Capturing is possible and cannot be replaced by other one?

like image 255
Uvuvwevwevwe Avatar asked Feb 16 '19 15:02

Uvuvwevwevwe


1 Answers

  • @Injectable mocks a single instance (e.g. a test method's parameter). Not every instance used inside the test context.
  • @Mocked will mock all class methods and constructors on every instance created inside the test context.
  • @Capturing is basically the same as @Mocked, but it extends mocking to every subtype of the annotated type (convinient!).

Another difference of @Injectable is that only fields marked with this annotation are considered for injection inside @Tested instances.

The difference should be pretty clear now.

like image 130
LppEdd Avatar answered Sep 28 '22 02:09

LppEdd