使用 Mockito 为私有最终静态内联变量设置值
Set value for private final static inlined variable using Mockito
我正在尝试测试一个调用另一个方法的方法,该方法使用私有最终静态变量初始化内联。然后我试图在测试 运行 时更改变量的值。我一直在尝试 spring 反射或为该特定字段添加 setter 之类的东西,但也许我应该使用我以前从未使用过的东西作为 powermock。我独自尝试实现这一点,没有人问我,所以请问我是否可以就什么是最好的方法提供一些指导。
更新
根据我在这里得到的一些反馈,模拟 private final 变量可能不是我应该为我的测试做的。我在这里打开了一个不同的问题
@Service
public class CookieSessionUtils {
private static final String VIADUCT_LOCAL_AMP = "viaductLocalAmp"; // Value to be changed when the test runs to test the "if Y" scenario.
public boolean verifyState(HttpServletRequest request, String state) {
String viaductLocalAmp = getCookieByName(request, VIADUCT_LOCAL_AMP);
if (viaductLocalAmp.equalsIgnoreCase("Y")) {
return true;
}
return false;
}
public String getCookieByName(HttpServletRequest request, String cookieName) {
try {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(cookieName)) {
return cookie.getValue();
}
}
}
} catch (Exception e) {
ExceptionLogger.logDetailedError("CookieSessionUtils.getCookieByName", e);
log.error("Error on Cookie " + e.getMessage());
}
return "";
}
这些是我尝试过的一些方法:
@Autowired
private CookieSessionUtils cookieSessionUtils;
@Mock
private HttpServletRequest request;
@Test
public void testVerifyState() {
Cookie mockCookie = Mockito.mock(Cookie.class);
Mockito.when(mockCookie.getName()).thenReturn("YviaductLocalAmp");
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{mockCookie});
// cookieSessionUtils.setViaductLocalAmp("YviaductLocalAmp");
// setField(cookieSessionUtils, "VIADUCT_LOCAL_AMP", VIADUCT_LOCAL_AMP);
// Mockito.when(cookieSessionUtils.getCookieByName(request, "YviaductLocalAmp")).thenReturn("Y");
assertTrue(cookieSessionUtils.verifyState(httpServletRequest, "viaductLocalAmp"));
}
谢谢。
不确定 Powermock 是否也能提供帮助。
推荐的方法是不使用需要在测试时更改的内联常量。
- 如果你想改变这个,你需要引入一个接口,在它们之间提供常量。将它的一种实现用于实际源代码,另一种用于测试。测试时切换实现。
如果你不想改变这个,你可以尝试下面的反射方法
- 使字段可访问。
- 删除最终修饰符
- 编辑字段值
那里得到了这个建议
private static void setFinalStatic(Field field, Object newValue) throws Exception {
Field field = ClassWhereToMockStaticFinalVar.class.getDeclaredField("FieldName");
field.setAccessible(true);
// remove final modifier from field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
您试图违反信息隐藏/封装原则,因为您试图“测试代码”。
但是单元测试不“测试代码”。
单元测试验证 public observable behavior,即:return values 与依赖项的通信。
该常量的实际内容是实现细节 测试不应关心。
所以你真正应该测试的是 verifyState()
returns true
如果 request 包含名称为“viaductLocalAmp”的 cookie " 和值 "Y"。
我正在尝试测试一个调用另一个方法的方法,该方法使用私有最终静态变量初始化内联。然后我试图在测试 运行 时更改变量的值。我一直在尝试 spring 反射或为该特定字段添加 setter 之类的东西,但也许我应该使用我以前从未使用过的东西作为 powermock。我独自尝试实现这一点,没有人问我,所以请问我是否可以就什么是最好的方法提供一些指导。
更新
根据我在这里得到的一些反馈,模拟 private final 变量可能不是我应该为我的测试做的。我在这里打开了一个不同的问题
@Service
public class CookieSessionUtils {
private static final String VIADUCT_LOCAL_AMP = "viaductLocalAmp"; // Value to be changed when the test runs to test the "if Y" scenario.
public boolean verifyState(HttpServletRequest request, String state) {
String viaductLocalAmp = getCookieByName(request, VIADUCT_LOCAL_AMP);
if (viaductLocalAmp.equalsIgnoreCase("Y")) {
return true;
}
return false;
}
public String getCookieByName(HttpServletRequest request, String cookieName) {
try {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(cookieName)) {
return cookie.getValue();
}
}
}
} catch (Exception e) {
ExceptionLogger.logDetailedError("CookieSessionUtils.getCookieByName", e);
log.error("Error on Cookie " + e.getMessage());
}
return "";
}
这些是我尝试过的一些方法:
@Autowired
private CookieSessionUtils cookieSessionUtils;
@Mock
private HttpServletRequest request;
@Test
public void testVerifyState() {
Cookie mockCookie = Mockito.mock(Cookie.class);
Mockito.when(mockCookie.getName()).thenReturn("YviaductLocalAmp");
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{mockCookie});
// cookieSessionUtils.setViaductLocalAmp("YviaductLocalAmp");
// setField(cookieSessionUtils, "VIADUCT_LOCAL_AMP", VIADUCT_LOCAL_AMP);
// Mockito.when(cookieSessionUtils.getCookieByName(request, "YviaductLocalAmp")).thenReturn("Y");
assertTrue(cookieSessionUtils.verifyState(httpServletRequest, "viaductLocalAmp"));
}
谢谢。
不确定 Powermock 是否也能提供帮助。
推荐的方法是不使用需要在测试时更改的内联常量。
- 如果你想改变这个,你需要引入一个接口,在它们之间提供常量。将它的一种实现用于实际源代码,另一种用于测试。测试时切换实现。
如果你不想改变这个,你可以尝试下面的反射方法
- 使字段可访问。
- 删除最终修饰符
- 编辑字段值
private static void setFinalStatic(Field field, Object newValue) throws Exception {
Field field = ClassWhereToMockStaticFinalVar.class.getDeclaredField("FieldName");
field.setAccessible(true);
// remove final modifier from field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
您试图违反信息隐藏/封装原则,因为您试图“测试代码”。
但是单元测试不“测试代码”。
单元测试验证 public observable behavior,即:return values 与依赖项的通信。
该常量的实际内容是实现细节 测试不应关心。
所以你真正应该测试的是 verifyState()
returns true
如果 request 包含名称为“viaductLocalAmp”的 cookie " 和值 "Y"。