我如何才能使用Mockito只进行正向测试



控制器使用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);
    }
}

您的问题是。。。

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()的调用将为零,因为它只进入mock,但您可以验证它

哦,你可以通过@InjectMocks自动创建ComputingController(以及注入mock)。。。

 @InjectMocks
 private ComputingController controller;

如果不修改ComputingController类的现有源代码,就不可能实现这一点。

如果你愿意修改ComputingController,下面是你可以做的模拟调用-updateData.doUpdateData()

  1. ComputingController中创建一个具有默认或protected级别可访问性的方法getUpdateData()private将不起作用,不建议使用public

UpdateData getUpdateData() {return new UpdateData();}

  1. ComputingController中的getUpdateData()替换new UpdateData();
  2. public class ComputingControllerTest中创建一个非公共类ComputingControllerTestable

class ComputingControllerTestable extends ComputingController { private UpdateData updateData; @Override protected void getUpdateData(){return updateData;} protected void setUpdateData(UpdateData updateData){this.updateData=updateData;} }

  1. 现在,在测试类中,将测试中的类型替换为ComputingControllerTestable,而不是ComputingController

  2. ComputingControllerTest中,声明一个模拟字段@Mock private UpdateData updateData;

  3. 现在,在测试类的@Before方法中,为测试类的模拟字段testObj.setUpdateData(updateData);调用ComputingControllerTestable的setter方法,其中testObj是步骤#4中创建的测试下的对象。

我假设被测试的类和测试类在同一个包中。

简单的方法(避免以上6个步骤)是在ComputingController类中将UpdateData对象声明为依赖项(实例字段),而不是每次在doGet方法中创建一个新的UpdateData,并在ComputingControllerTest 中模拟该依赖项

希望它能有所帮助!!

相关内容

  • 没有找到相关文章

最新更新