如何通过 Mockito.mockStatic(SpringUtils.class) 模拟 SpringUtils.getBean("beanName")
How to mock SpringUtils.getBean("beanName") by Mockito.mockStatic(SpringUtils.class)
当我尝试使用 Mockito 3.7.7 模拟像 SpringUtils.getBean("BeanName") 这样的静态方法时,我得到了 applicationContext 的 NullPointerException,并且 getBean("BeanName") 方法似乎仍然存在已执行,这是我的代码:
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringUtils.applicationContext = applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
// NullPointerException here
return (T) applicationContext.getBean(name);
}
}
这是我使用 SpringUtils 的地方:
public class Aaa{
public Integer getSpringBean(){
RedisTemplate<String,Object> redisTemplate = SpringUtils.getBean("abc");
System.out.println(1234);
return 5;
}
}
测试代码为:
@Test
public void test(){
Aaa a = new Aaa();
try (MockedStatic<SpringUtils> theMock1 = Mockito.mockStatic(SpringUtils.class)) {
theMock1.when(()->SpringUtils.getBean(Mockito.anyString())).thenReturn(Mockito.mock(RedisTemplate.class));
}
Integer x = a.getSpringBean();
System.out.println(x);
}
然后我得到一个 NullPointerException:
java.lang.NullPointerException
at com.labs.common.idgenerator.utils.SpringUtils.getBean(SpringUtils.java:42)
at com.labs.common.idgenerator.config.Aaa.getSpringBean(Aaa.java:24)
那么,如何使用 mockito 正确模拟 SpringUtils.getBean("beanName")?
此致!
您正在使用 try-with-resources 块来管理您的 MockedStatic。
这意味着 MockedStatic 对象在进入此块时创建,但在退出块时资源自动关闭。
Releases this static mock and throws a MockitoException if closed already.
必须在 MockedStatic 仍处于活动状态时完成与存根静态方法的所有交互 - 在 try-with-resources 块的范围内:
try (MockedStatic<SpringUtils> theMock1 = Mockito.mockStatic(SpringUtils.class)) {
theMock1.when(()->SpringUtils.getBean(Mockito.anyString()))
.thenReturn(Mockito.mock(RedisTemplate.class));
Aaa a = new Aaa();
Integer x = a.getSpringBean();
System.out.println(x);
}
我作为伙伴尝试了代码,它工作正常,但我不太确定它是不是一个好的解决方案:
@Test
public void test(){
CodeRuleConfig config = null;
try(
//spring utils
MockedStatic spring = mockStatic(SpringUtils.class);
//config center, depends on SpringUtils
MockedStatic gaea = mockStatic(GaeaUtils.class);
//RedisUtils, depends on SpringUtils
MockedStatic redis = mockStatic(RedisUtils.class)
){
spring.when(()->SpringUtils.getBean(Environment.class)).thenReturn(MockData.mockEnv());
gaea.when(()->GaeaUtils.getCodeRuleConfig(Mockito.anyString())).thenReturn(MockData.getCodeRuleConfig());
redis.when(()->RedisUtils.hIncrBy(Mockito.anyString(),Mockito.any(),Mockito.anyLong())).thenReturn(999L);
System.out.println(IdGenerator.getInstance().nextCode("orderNo"));
}
}
当我尝试使用 Mockito 3.7.7 模拟像 SpringUtils.getBean("BeanName") 这样的静态方法时,我得到了 applicationContext 的 NullPointerException,并且 getBean("BeanName") 方法似乎仍然存在已执行,这是我的代码:
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringUtils.applicationContext = applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
// NullPointerException here
return (T) applicationContext.getBean(name);
}
}
这是我使用 SpringUtils 的地方:
public class Aaa{
public Integer getSpringBean(){
RedisTemplate<String,Object> redisTemplate = SpringUtils.getBean("abc");
System.out.println(1234);
return 5;
}
}
测试代码为:
@Test
public void test(){
Aaa a = new Aaa();
try (MockedStatic<SpringUtils> theMock1 = Mockito.mockStatic(SpringUtils.class)) {
theMock1.when(()->SpringUtils.getBean(Mockito.anyString())).thenReturn(Mockito.mock(RedisTemplate.class));
}
Integer x = a.getSpringBean();
System.out.println(x);
}
然后我得到一个 NullPointerException:
java.lang.NullPointerException
at com.labs.common.idgenerator.utils.SpringUtils.getBean(SpringUtils.java:42)
at com.labs.common.idgenerator.config.Aaa.getSpringBean(Aaa.java:24)
那么,如何使用 mockito 正确模拟 SpringUtils.getBean("beanName")?
此致!
您正在使用 try-with-resources 块来管理您的 MockedStatic。 这意味着 MockedStatic 对象在进入此块时创建,但在退出块时资源自动关闭。
Releases this static mock and throws a MockitoException if closed already.
必须在 MockedStatic 仍处于活动状态时完成与存根静态方法的所有交互 - 在 try-with-resources 块的范围内:
try (MockedStatic<SpringUtils> theMock1 = Mockito.mockStatic(SpringUtils.class)) {
theMock1.when(()->SpringUtils.getBean(Mockito.anyString()))
.thenReturn(Mockito.mock(RedisTemplate.class));
Aaa a = new Aaa();
Integer x = a.getSpringBean();
System.out.println(x);
}
我作为伙伴尝试了代码,它工作正常,但我不太确定它是不是一个好的解决方案:
@Test
public void test(){
CodeRuleConfig config = null;
try(
//spring utils
MockedStatic spring = mockStatic(SpringUtils.class);
//config center, depends on SpringUtils
MockedStatic gaea = mockStatic(GaeaUtils.class);
//RedisUtils, depends on SpringUtils
MockedStatic redis = mockStatic(RedisUtils.class)
){
spring.when(()->SpringUtils.getBean(Environment.class)).thenReturn(MockData.mockEnv());
gaea.when(()->GaeaUtils.getCodeRuleConfig(Mockito.anyString())).thenReturn(MockData.getCodeRuleConfig());
redis.when(()->RedisUtils.hIncrBy(Mockito.anyString(),Mockito.any(),Mockito.anyLong())).thenReturn(999L);
System.out.println(IdGenerator.getInstance().nextCode("orderNo"));
}
}