Controller使用request.getParameter转发,代码如下
public class ComputingController extends HttpServlet {
public ComputingController() {
super();
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String reDirect = request.getParameter("redirect");
RequestDispatcher rd = null;
if ( "update".equals( reDirect ) ) {
UpdateData updateData = new UpdateData();
String updateResult = updateData.doUpdateData();
request.setAttribute( "updateResult", updateResult );
rd = request.getRequestDispatcher("WEB-INF/jsp/computing/success.jsp");
rd.forward(request, response);
}
else {
rd = request.getRequestDispatcher("WEB-INF/jsp/computing/error.jsp");
rd.forward(request, response);
}
}
}
我使用Junit和Mockito来测试前进。
但是当我执行测试时(如下所示),它将在控制器中执行updateData.doUpdateData()。
我如何使用Mockito让它不执行updateData.doUpdateData()但是转发?
public class ComputingControllerTest {
@Mock
HttpServletRequest request;
@Mock
HttpServletResponse response;
@Mock
RequestDispatcher rd;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
public void doGet_testForward() throws Exception {
String reDirect = "update";
when(request.getParameter("redirect")).thenReturn( reDirect );
when(request.getRequestDispatcher("WEB-INF/jsp/computing/success.jsp")).thenReturn(rd);
new ComputingController().doGet(request, response);
verify(rd).forward(request, response);
}
}
答案 0 :(得分:2)
你的问题是这个......
UpdateData updateData = new UpdateData();
String updateResult = updateData.doUpdateData();
request.setAttribute( "updateResult", updateResult );
你不能完全跳过它,只修改你的测试你就不会走得太远。所以,你需要的是一种在那里注入另一个UpdateData()的方法(然后你可以模拟)。例如,一种可能性是工厂模式......
private UpdateDataFactory factory;
public ComputingController(UpdateDataFactory factory) {
super();
this.factory = factory;
}
public ComputingController() {
super(new DefaultUpdataDataFactory()); // simply creates a new UpdateData();
this.factory = factory;
}
现在你可以写了......
UpdateData updateData = this.factory.createUpdataData();
在测试中,你可以模拟工厂并插入它......
@Mock
private UpdateDataFactory factory;
@Mock
private UpdateData data;
...
when(factory.createUpdataData()).thenReturn (data);
new ComputingController(factory).doGet(request, response);
现在对doUpdataData()的调用将一无所获,因为它只会进入模拟,但你可以验证它
哦,你可以通过@InjectMocks自动创建ComputingController(并注入模拟)......
@InjectMocks
private ComputingController controller;
答案 1 :(得分:2)
如果不修改ComputingController
类的现有源代码,就无法实现这一目标。
如果您愿意修改ComputingController
,则可以使用以下内容模拟通话 - updateData.doUpdateData()
,
getUpdateData()
中使用默认或ComputingController
级别辅助功能创建方法protected
(private
不起作用且不建议使用public
), UpdateData getUpdateData() {return new UpdateData();}
new UpdateData();
替换为getUpdateData()
ComputingController
ComputingControllerTestable
public class ComputingControllerTest
醇>
class ComputingControllerTestable extends ComputingController {
private UpdateData updateData;
@Override protected void getUpdateData(){return updateData;}
protected void setUpdateData(UpdateData updateData){this.updateData=updateData;}
}
现在,在您的测试类中,将测试中类类型替换为ComputingControllerTestable
而不是ComputingController
在ComputingControllerTest
中,声明一个模拟字段,@Mock private UpdateData updateData;
现在,在您的@Before
测试类方法中,为测试类的模拟字段ComputingControllerTestable
调用testObj.setUpdateData(updateData);
的setter方法,其中testObj
为在第4步中创建的测试阶段对象。
我假设您的测试类和测试类在同一个包中。
简单方法(避免上述所有6个步骤)是将UpdateData
对象声明为ComputingController
类中的依赖项(实例字段),而不是每次在UpdateData
内创建新doGet
{1}}方法并在ComputingControllerTest
希望它有所帮助!!