Mockito和ReloadableResourceBundleMessageSource不能很好地配合使用?

ep6jt1vc  于 2022-11-08  发布在  其他
关注(0)|答案(5)|浏览(176)

我有一个简单的测试,它甚至不是一个测试,因为我只是想模拟消息源。
我得到这个错误:

org.springframework.context.NoSuchMessageException: No message 
found under code '' for locale 'null'.

还有其他人可以验证这种行为吗?
这是我设置的一个最小的Spring引导框架测试,因为ReloadableResourceBundleMessageSource在另一个项目中不起作用,所以我想我将在尽可能小的单元中尝试它。

@RunWith(MockitoJUnitRunner.class)
public class DemoApplicationTests {

    @Test
    public void contextLoads() {

    ReloadableResourceBundleMessageSource messageSource = 
    mock(ReloadableResourceBundleMessageSource.class);
    when(
       messageSource.getMessage(
           anyString(), 
           any(Object[].class), 
           any(Locale.class)
         )
       ).thenReturn("returnValue");

    System.out.println("test");

    } 
}

这是我得到的错误:

org.springframework.context.NoSuchMessageException: No message 
found under code '' for locale 'null'.

at org.springframework.context.support.AbstractMessageSource.getMessage(
AbstractMessageSource.java:159)
at com.example.DemoApplicationTests.contextLoads(
DemoApplicationTests.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at ....
....
....
....
com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(
JUnit4IdeaTestRunner.java:117)
at com.intellij.rt.execution.junit.JUnitStarter.
prepareStreamsAndStart(
JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(
JUnitStarter.java:74)

在我看来,它不能正确地模拟它。我也试过模拟MessageSource接口,但没有成功。

thigvfpy

thigvfpy1#

正如戴维·华莱士所说:
Mockito不能stub“final”方法,并且由于'getMessage'被声明为final,因此您不能对其进行模拟。

enyaitl3

enyaitl32#

我不想使用PowerMock,我解决了这个问题,创建了一个真正的ReloadableResourceBundleMessageSource bean,并将其注入到我想测试的类中

// create the real bean
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(-1);
messageSource.setBasenames("classpath:conf-test/messages"); // this folder is just for testing and it contains a messages_en.properties file

// inject the bean into the class I wanted to test
ReflectionTestUtils.setField(service, "messageSource", messageSource);
esbemjvw

esbemjvw3#

我找到了一个变通办法,在这种情况下,可以绕过mockito对mocking final方法的限制。
我没有嘲笑,而是在构造类之后设置它,如下所示:

ReloadableResourceBundleMessageSource bundleMessageSource = new ReloadableResourceBundleMessageSource();
bundleMessageSource.setUseCodeAsDefaultMessage(true);

根据官方文件:
返回是否使用消息代码作为默认消息,而不是抛出NoSuchMessageException。对于开发和调试很有用。默认值为“false”。

llew8vvj

llew8vvj4#

Final方法不能模仿。所以我写了一个这样的解决方案。

ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setUseCodeAsDefaultMessage(true);
    ReflectionTestUtils.setField(service, "messageSource", messageSource);
bcs8qyzn

bcs8qyzn5#

我已经成功地模拟了ResourceBundleMessageSource结合Mockito和PowerMockito(根据这个thread)。
下面是我的单元测试的摘录:

@RunWith(PowerMockRunner.class)
@PrepareForTest({..., ResourceBundleMessageSource.class})
public class ClassUnderTest {
   @Mock
   ResourceBundleMessageSource resourceBundleMessageSourceMock;

   @Test
   public void myTest() {
      // Given
      ...;

      // When
      PowerMockito.mockStatic(ResourceBundleMessageSource.class);

      Mockito.when(resourceBundleMessageSourceMock.getMessage(ArgumentMatchers.anyString(), ArgumentMatchers.any(Object[].class),
        ArgumentMatchers.any(Locale.class)).thenReturn("aString");

      // Then
      ...;
   }

}

相关问题