使用 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 是否也能提供帮助。

推荐的方法是不使用需要在测试时更改的内联常量。

  • 如果你想改变这个,你需要引入一个接口,在它们之间提供常量。将它的一种实现用于实际源代码,另一种用于测试。测试时切换实现。

如果你不想改变这个,你可以尝试下面的反射方法

  • 使字段可访问。
  • 删除最终修饰符
  • 编辑字段值

我从 this discussion

那里得到了这个建议
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"。