代码之家  ›  专栏  ›  技术社区  ›  Arthur Ronald

模拟与实现。如何在一个测试类中共享这两种方法?

  •  0
  • Arthur Ronald  · 技术社区  · 15 年前

    使用spring/spring mvc查看下面的模拟测试

    public class OrderTest {
    
        // SimpleFormController
        private OrderController controller;
        private OrderService service;
    
        private MockHttpServletRequest request;
    
        @BeforeMethod
        public void setUp() {
    
            request = new MockHttpServletRequest();
            request.setMethod("POST");
    
            Integer orderNumber = 421;
            Order order = new Order(orderNumber);
    
            // Set up a Mock service
            service = createMock(OrderService.class);
            service.save(order);
    
            replay(service);
    
            controller = new OrderController();
            controller.setService(service);
            controller.setValidator(new OrderValidator());
    
            request.addParameter("orderNumber", String.valueOf(orderNumber));
        }
    
        @Test
        public void successSave() {
            controller.handleRequest(request, new MockHttpServletResponse());
    
            // Our OrderService has been called by our controller
            verify(service);
        }
    
        @Test
        public void failureSave() {
            // Ops... our orderNumber is required
            request.removeAllParameters();
    
            ModelAndView mav = controller.handleRequest(request, new MockHttpServletResponse());
    
            BindingResult bindException = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + "command");
    
            assertEquals("Our Validator has thrown one FieldError", bindException.getAllErrors(), 1);
        }
    
    }
    

    如你所见,我是按照 Triple A pattern

    • 排列(设置方法)
    • Act(控制器。handlerequest)
    • 断言(verify和assertequals)

    但是我想通过使用这个测试类来测试mock和实现类(orderservice) . 为了检索我的实现,我重新编写了如下类

    @ContextConfiguration(locations="/app.xml")
    public class OrderTest extends AbstractTestNGSpringContextTests {
    
    
    
    }
    

    那么我应该如何编写我的单个测试 安排 模拟和实现OrderService 不改变我的测试方法 (成功保存和失败保存)

    我正在使用testng,但是如果你想的话可以用junit显示

    当做,

    3 回复  |  直到 15 年前
        1
  •  1
  •   Kannan Ekanath    15 年前

    对我来说,这看起来像是两个不同的测试,但如果你要坚持的话:)在这里

    @SpringJunit4Runner(....="app.xml")
    public class OrderTest {
    
        @Resource
        private OrderController controller; //bean from app.xml
    
        @Resource
        private OrderService service; // actual order service
        private OrderService mockOrderService; //some mock order service
        private MockHttpServletRequest request;
    
        @BeforeMethod
        public void setUp() {
            request = new MockHttpServletRequest();
            request.addParameter("orderNumber", String.valueOf(orderNumber));
        }
    
        @Test
        public void successSave() {
            //test with orderService the way you would do it
        }
    
        @Test
        @DirtiesContext
        //need the annotation because we are changing our context beans i.e, ordercontroller
        //so for the next test the context would be recreated
        public void successSaveWithMock() {
            mockOrderService = //create mock service
            orderController.setOrderService(mockOrderService);
            //do the test with mock
        }
    }
    

    这是针对JUnit4的,但对于您的测试,它应该是相同/相似的原则。我再次假设你已经做了关于为什么你需要在同一个文件中进行单元测试和集成测试的研究!!!!

        2
  •  2
  •   Arne Burmeister    15 年前

    这是非常不同的测试类型。第一个是测试控制器单元的典型单元测试。第二个是一个小型集成测试,测试控制器和服务的交互以及spring配置。

    所以不要把第一个测试换成第二个,这是另外一个!

        3
  •  1
  •   Péter Török    15 年前

    对我来说,这将是两个不同的测试(准确地说是测试集)。我想说测试 OrderController 与测试不同 OrderService ,即使两个测试设置中都有类似的元素。单元测试值一次测试一件事(一个用例和一个对象)的简单测试,以及有充分理由的imho。每个类都有自己的接口契约,有自己的边界条件,应该单独测试。

    而且,要想测试是很困难的 订单服务 通过控制器,而不是直接在测试方法中调用它。很可能,当通过控制器调用时,在传递“棘手的”参数以执行边界条件等方面,您将没有那么多的自由。

    因此,我建议编写两个独立的测试类,这两个类都完全专注于测试自己的类。然后,当您对单元测试感到满意并且不再知道要测试什么时,您可以查看setup和helper方法,看看是否可以通过一些重构来删除一些重复项。但对我来说,在我的测试类中保存几行代码并不是首要考虑的问题。重点是测试所有可能中断的内容,并保持测试的简单性,以明确这个测试实际上是在测试什么。尝试同时测试两个对象肯定会使您的测试更难理解(从而在长期内维护)。