我试图模拟一个在另一个方法中递归调用的方法。
public class ABC
{
public static Object getSessionAttribute(String value) {
return Context.current().getHttpSession().getAttribute(value);
}
public static String myMethod(String xyz) throws Exception{
/*Some important business logic*/
String abc = getSessionAttribute("abcdefghj").toString();
/*Some important business logic*/
return abc;
}
}
我的测试课是这样的;
@RunWith(PowerMockRunner.class)
@PrepareForTest(ABC.class)
public class ABCTest {
@Before
public void setUp() throws Exception {
PowerMockito.mockStatic(ABC.class, Mockito.CALLS_REAL_METHODS);
PowerMockito.when(ABC.getSessionAttribute("dummyValue")).thenReturn("myReturnValue");
}
@Test
public void testmyMethod() throws Exception {
Assert.assertEquals("anyValue", ABC.myMethod("value"));
}
}
在这里,我从 ** 返回 Context.current().getHttpSession().getAttribute(value)** 行中得到一个 NullPointerException。我认为它希望我模拟从上下文到.getAttribute的每个类。我怎样才能让它工作?
注意:我对powermock一无所知,但我使用过其他模拟工具。
代码的问题在于它整齐地耦合到Context.current().getHttpSession()
如果你用HttpSession
接口替换Context.current().getHttpSession()
并使类方法非静态,它可以很容易地像这样模拟和测试。
public class ABC
{
HttpSession session;
public ABC(HttpSession session) {
this.session = session;
}
private Object getSessionAttribute(String value) {
return this.session.getAttribute(value);
}
public String myMethod(String xyz) throws Exception{
/*Some important business logic*/
String abc = getSessionAttribute("dummyValue").toString();
/*Some important business logic*/
return abc;
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(ABC.class)
public class ABCTest {
HttpSession sessionMock;
@Before
public void setUp() throws Exception {
sessionMock = ... create a mock that implements the interface HttpSession
PowerMockito
.when(sessionMock.getSessionAttribute("dummyValue"))
.thenReturn("myReturnValue");
}
@Test
public void testmyMethod() throws Exception {
ABC sut = new ABC(sessionMock);
Assert.assertEquals("anyValue", sut.myMethod("value"));
}
}
你能在你的代码中分享你的导入吗?我可以为您模拟上下文对象,但我不确定它是哪个 JAR 的一部分。
下面的代码被认为是Java火车的残骸,它使单元测试更加痛苦。
return Context.current().getHttpSession().getAttribute(value);
我建议通过提取局部变量来重构上面的代码。Martin Fowlwer的建议也在这里:
"模拟测试人员确实更多地谈论避免'火车残骸' - getThis().getThat().getTheOther()风格的方法链。避免方法链也称为遵循得墨忒耳定律。虽然方法链是一种气味,但中间人对象与转发方法臃肿的相反问题也是一种气味。