Mariusz Grodek
Mariusz Grodek

Reputation: 639

Mocked method not called in Mockito

Hello I have one service with a method:

@Service
public class CaptchaServiceImpl implements CaptchaService {

@Autowired
private MessageSource messageSource;

@Override
public boolean processCaptcha(String requestedUrl, String challenge, String userResponse) {

    ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
    reCaptcha.setPrivateKey(messageSource.getMessage("reCaptcha.private.key", new Object[]{}, new Locale("pl", "PL")));
    ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(requestedUrl, challenge, userResponse);

    return reCaptchaResponse.isValid();
}

}

and I wrote a test for it:

@RunWith(MockitoJUnitRunner.class)
public class CaptchaServiceImplTest {

private CaptchaService captchaService;

@Mock
private MessageSource messageSource;

@Mock
private ReCaptchaImpl reCaptcha;

@Before
public void init() {
    captchaService = new CaptchaServiceImpl();
    ReflectionTestUtils.setField(captchaService, "messageSource", messageSource);
}

@Test
public void shouldPassReCaptchaValidation() {
    ReCaptchaTestResponse captchaResponse = new ReCaptchaTestResponse(true, "no errors");
    when(messageSource.getMessage("reCaptcha.private.key", new Object[]{}, new Locale("pl", "PL"))).thenReturn("reCaptcha.private.key");
    when(reCaptcha.checkAnswer(anyString(), anyString(), anyString())).thenReturn(captchaResponse);

    boolean reCaptchaResponse = captchaService.processCaptcha("url", "challenger", "userResponse");

    assertThat(reCaptchaResponse, is(true));
}

private class ReCaptchaTestResponse extends ReCaptchaResponse {

    protected ReCaptchaTestResponse(boolean valid, String errorMessage) {
        super(valid, errorMessage);
    }
}

}

ReCaptchaResponse is protected class...

So when I run my test I am getting:

 java.lang.AssertionError: 
 Expected: is <true>
 got: <false>

For some reason my mocked method checkAnswer is never called and my captchaResponse object is never returned and I have ran out of ideas why. Could someone tell my why it is happening? Maybe I am missing something :/

UPDATE:

So I have updated my CaptchaService:

@Autowired
private ReCaptchaImpl reCaptcha;

@Override
public boolean processCaptcha(String requestedUrl, String challenge, String userResponse) {
    reCaptcha.setPrivateKey(messageSource.getMessage("reCaptcha.private.key", new Object[]{}, new Locale("pl", "PL")));
    ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(requestedUrl, challenge, userResponse);

    return reCaptchaResponse.isValid();
}

and now test is green! :) Thanks

Upvotes: 2

Views: 11671

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500515

This is the problem:

ReCaptchaImpl reCaptcha = new ReCaptchaImpl();

That's just creating a new instance - your mock isn't being used at all. Note how you're not passing your mock into anything - how did you expect the production code to use it?

Mocks are good for injected dependencies, or even dependencies which are returned by a factory where you can make the factory return the mock for you - but you're just calling the constructor.

You could use PowerMock for this, but I'd suggest redesigning either to avoid needing the mock at all, or to allow the dependency to be injected somewhere.

Upvotes: 7

Related Questions