Search code examples
jmockit

Why is there a NPE on @Injectable class


I have a class(looks something like this) I'm trying to test.

@Component
@Path("/user")
@Produces(MediaType.APPLICATION_JSON)
public class UserResource extends BaseResource {
    @Autowired UserService userService;

    @POST
    @Path("register")
    public User registerUser(User user){
        ...
        User registeredUser = userService.register(user);
        ...
        return registeredUser;
    }
}

The test looks like this.

public class UserResourceTest {
    @Tested UserResource userResource;
    @Injectable UserService userService;
    @Mocked BaseResource baseResource;

    @Test
    public void registerShouldDoSomething(){
        User user = new User();
        final User registerResult = new User();
        ...
        new NonStrictExpectations() {{
            userService.register((User)any); result = registerResult;
        }};
        userResource.registerUser(user);
        ...
    }
}

For some reason in the tested class, userService is null and throwing a NPE when register is called on it (UserService is a class not interface/abstract btw). I'm wondering if perhaps some of the annotations(javax or Spring) may be clashing with JMockit or something(Although I've tried removing them)?

I've tried switching the injectable to just @Mocked, and I've tried removing it and having it be a @Mocked test method param. Nothing seems to be solving the NPE.


Solution

  • I ended up using reflection to manually set the @Injectable fields in the @Tested class

    public class UserResourceTest {
        @Tested UserResource userResource;
        @Injectable UserService userService;
        @Mocked BaseResource baseResource;
    
        @Test
        public void registerShouldDoSomething(){
            Deencapsulation.setField(userResource,userService); //This line
            User user = new User();
            final User registerResult = new User();
            ...
            new NonStrictExpectations() {{
                userService.register((User)any); result = registerResult;
            }};
            userResource.registerUser(user);
            ...
        }
    }
    

    Still not sure what the bug is, but this works for me