0

I have a problem with mocking up the EntityManager. Everything compiles, the test runs but the mocked method returns null.

When I set the breakpoint inside the mocked 'find' method the app is never suspended there. I managed to successfully mock different class with static methods this way - but with this one I have problems.

I use Jmockit 1.7 along with Java 1.8.0. The class I am trying to mock is: javax.persistence.EntityManager

If there are any more information needed - please ask. I would be very grateful for any help.

Here is my code:

@RunWith(JMockit.class)
public class ShapefileSerializerTest {

    @Mocked
    private EntityManager em;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        new MockDatabase();
    }

    @Test
    public void testPrepareShapefile() {
        String[][] data = new String[][] {{"1", "100"}, {"1", "101"}, {"1", "102"}, {"1", "103"}, {"2", "200"}, {"2", "201"}};

        List<Map<String, String>> featuresData = Stream.of(data).map(row -> {
            Map<String, String> map = new HashMap<>(2);
            map.put("layerId", row[0]);
            map.put("id", row[1]);
            return map;
        }).collect(Collectors.toList());

        ShapefileSerializer shapefileSerializer = new ShapefileSerializer("shapefiles");
        // if I do not set up the em here - then it will be null inside the tested class
        Deencapsulation.setField(shapefileSerializer, em);

        Response response = shapefileSerializer.prepareShapefile(featuresData);

        assertEquals(Status.OK.getStatusCode(), response.getStatus());
    } 

    public static final class MockDatabase extends MockUp<EntityManager> {
        @Mock
        @SuppressWarnings("unchecked")
        public <T> T find(Class<T> entityClass, Object primaryKey) {
            return (T) new ProjectLayer();
        }
    }
}
Marcin Roguski
  • 729
  • 2
  • 7
  • 16

1 Answers1

0

Upgrade JMockit to version 1.8 or newer, and change your test class to the following:

@RunWith(JMockit.class)
public class ShapefileSerializerTest {
    @Mocked EntityManager em;

    @Test
    public void testPrepareShapefile() {
        String[][] data = ...
        List<Map<String, String>> featuresData = ...

        ShapefileSerializer shapefileSerializer = new ShapefileSerializer("shapefiles");
        Deencapsulation.setField(shapefileSerializer, em);

        new Expectations() {{
            em.find((Class<?>) any, any); result = new ProjectLayer();
        }};

        Response response = shapefileSerializer.prepareShapefile(featuresData);

        assertEquals(Status.OK.getStatusCode(), response.getStatus());
    } 
}
Rogério
  • 16,171
  • 2
  • 50
  • 63
  • Thanks for the post. Unfortunately this did not work. I get the following exception from the expectations block: IllegalArgumentException: Invalid type descriptor: (Ljava/lang/Class;Ljava/lang/Object;)java/lang/Object; This line causes the error: result = new ProjectLayer(); I tried this before and got the same exception. – Marcin Roguski Jan 29 '15 at 07:19
  • @MarcinRoguski It was a bug in version 1.7, fixed for 1.8. So, you'll need to upgrade JMockit to version 1.8 or newer. – Rogério Jan 29 '15 at 13:34
  • @ Rogério Thanks, that solved the issue with Expectations :) However I still do not know why Mocking up EntityManager did not work. I also tried it with another class and still the same. The mocked method is not being called. Even despite the fact that it is instantiated and passed to the tested class using: Deencapsulation.setField(shapefileSerializer, em); – Marcin Roguski Jan 30 '15 at 06:22
  • @MarcinRoguski Because `MockUp`s have nothing to do with `@Mocked` fields. Also, when mocking-up a Java *interface* (rather than a class), you need to call `getMockInstance()` and use the returned instance, otherwise it has no effect. – Rogério Jan 30 '15 at 16:18