Spring LocaleContextHolder not correctly set

给你一囗甜甜゛ 提交于 2021-01-29 17:13:13

问题


I'm having some issues with Spring LocaleContextHolder.

I have the following code:

public void sendPasswordRecoverySmsAsync(String phone) {
    CompletableFuture.runAsync(() -> {
        sendPasswordRecoverySmsSync(phone);
    });
}

public void sendPasswordRecoverySmsSync(String phone) {
    User user = userDao.findByPhone(phone, User.class).orElseThrow(() -> new UserNotFoundException(phone));
    log.info("User found, recovering password");
    user.setUpdateTime(LocalDateTime.now());
    userDao.save(user);

    int otp = codesGenerator.generateOtp(user.getUpdateTime());

    // Sends the SMS.
    Locale locale = LocaleContextHolder.getLocale();
    System.out.println("locale " + locale);
    String appName = messageSource.getMessage("app.name", null, locale);
    String smsContent = messageSource.getMessage("sms.password.recovery", new Object[] { otp }, locale);
    Message message = new TextMessage(appName, phone, smsContent);
    try {
        smsClient.submitMessage(message);
    } catch (NexmoClientException | IOException e) {
        log.error("Error while sending recovery password message to phone number [{}]", phone, e);
        throw new UserActivationException("Error while recovering password for user with phone: " + phone, e);
    }
}

and this test:

@Before
public void setup() {
    LocaleContextHolder.resetLocaleContext();
    Mockito.when(tokenGenerator.generateOtp(Mockito.any())).thenReturn(14);
}

@Test(timeout = 3000)
public void testSendPasswordRecoverySmsAsyncError() throws Exception {
    // Mocks.
    LocaleContextHolder.setLocale(Locale.ENGLISH, true);
    String mockPhone = "333";
    User mockUser = mockModelBuilder.user(true, true);
    Mockito.when(userDao.findByPhone(mockPhone, User.class)).then(r -> {
        // TODO
        return Optional.of(mockUser);
    });
    CountDownLatch latch = new CountDownLatch(1);
    ArgumentCaptor<TextMessage> messageCaptor = ArgumentCaptor.forClass(TextMessage.class);
    Mockito.when(smsClient.submitMessage(messageCaptor.capture())).then(r -> {
        latch.countDown();
        throw new NexmoClientException();
    });

    // Test.
    service.sendPasswordRecoverySmsAsync(mockPhone);
    latch.await();

    // Assertions.
    Assert.assertTrue(true);
    TextMessage actualMessage = messageCaptor.getValue();
    Assert.assertEquals("myApp", actualMessage.getFrom());
    Assert.assertEquals(mockPhone, actualMessage.getTo());
    Assert.assertEquals("Your password recovery code for myApp app is 14", actualMessage.getMessageBody());
}

I would expect the ouput of my test being "en" and this works properly if I launch only this one. However, when I run all my tests, the ouput is "it". This is probably either because in other tests I set an ITALIAN locale or because it's getting the system default.

But why is it getting the wrong one even when I'm resetting it explicitly?


回答1:


For solely the purpose of testing such localization cases, you might just need to add the following on your test method. This will essentially mark the context Dirty and recreate it, depending on whether you mention as the context being Dirty either before or After the test execution.

@DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
@Test(timeout = 3000)
public void testSendPasswordRecoverySmsAsyncError() throws Exception {...

Please refer the documentation here

Hope this helps, as it resolved a similar problem for me.



来源:https://stackoverflow.com/questions/60204379/spring-localecontextholder-not-correctly-set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!