首页 > 解决方案 > 如何断言在 void 方法中创建的值?

问题描述

我有课

public class CloneUserService {

    private final UserRepository userRepository;
    private final PersonRepository personRepository;
    private final OrderRepository orderRepository;

    public CloneUserService(UserRepository userRepository, PersonRepository personRepository, OrderRepository orderRepository) {
        this.userRepository = userRepository;
        this.personRepository = personRepository;
        this.orderRepository = orderRepository;
    }


    public void createFromTemplate(String templateUserId) {
        User templateUser = userRepository.getUserById(templateUserId);
        Person templatePerson = personRepository.getPersonByUserId(templateUserId);
        List<Order> templateOrders = orderRepository.getOrdersByUserId(templateUserId);

        User newUser = cloneUserFromTemplate(templateUser);
        newUser.setId("newId");
        userRepository.save(newUser);

        Person newPerson = clonePersonFromTemplate(templatePerson);
        newPerson.setUser(newUser);
        newPerson.setId("newId");
        personRepository.save(newPerson);

        for (Order templateOrder : templateOrders) {
            Order newOrder =  cloneOrderFromTemplate(templateOrder);
            newOrder.setId("newId");
            newOrder.setUSer(newUser);
            orderRepository.save(newOrder);
        }

    }

    private Order cloneOrderFromTemplate(Order templateOrder) {
        //logic
        return null;
    }

    private Person clonePersonFromTemplate(Person templatePerson) {
        //logic
        return null;
    }

    private User cloneUserFromTemplate(User templateUser) {
        //logic
        return null;
    }
}

我需要测试这个方法createFromTemplate

我创建了这个测试。我为每个存储库创建 stab,并将保存的对象存储到这个存根中。我添加了额外的方法来获取这个对象的断言。有用。但我有两个问题:

  1. 我的模板对象是可变的。这不是一个大问题,但这是一个事实。
  2. 如果我向存储库接口添加新方法,我必须在存根中实现它。

Mu 问题 - 如何从我的示例中测试像论文这样的克隆对象?

我不使用 spring 和 H2DB 或其他内存数据库。我有一个 MongoDB 数据库。如果我使用 mockito,我将不明白如何在 void 方法中断言新对象。

class CloneUserServiceTest {

    private CloneUserService cloneUserService;
    private UserRepositoryStub userRepository;
    private PersonRepositoryStub personRepository;
    private OrderRepositoryStub orderRepository;

    @Before
    public void setUp() {
        User templateUser = new User();
        Person templatePerson = new Person();
        List<Order> templateOrders = Collections.singletonList(new Order());

        userRepository = new UserRepositoryStub(templateUser);
        personRepository = new PersonRepositoryStub(templatePerson);
        orderRepository = new OrderRepositoryStub(templateOrders);

        cloneUserService = new CloneUserService(userRepository, personRepository, orderRepository);
    }

    @Test
    void createFromTemplate() {
        cloneUserService.createFromTemplate("templateUserId");

        User newUser = userRepository.getNewUser();
//        assert newUser
        Person newPerson = personRepository.getNewPerson();
//        assert newPerson
        Order newOrder = orderRepository.getNewOrder();
//        assert newOrder
    }

    private static class UserRepositoryStub implements UserRepository {
        private User templateUser;
        private User newUser;

        public UserRepositoryStub(User templateUser) {
            this.templateUser = templateUser;
        }

        public User getUserById(String templateUserId) {
            return templateUser;
        }

        public void save(User newUser) {
            this.newUser = newUser;
        }

        public User getNewUser() {
            return newUser;
        }
    }

    private static class PersonRepositoryStub implements PersonRepository {
        private Person templatePerson;
        private Person newPerson;

        public PersonRepositoryStub(Person templatePerson) {
            this.templatePerson = templatePerson;
        }

        public Person getPersonByUserId(String templateUserId) {
            return templatePerson;
        }

        public void save(Person newPerson) {
            this.newPerson = newPerson;
        }

        public Person getNewPerson() {
            return newPerson;
        }
    }

    private static class OrderRepositoryStub implements OrderRepository {
        private List<Order> templateOrders;
        private Order newOrder;

        public OrderRepositoryStub(List<Order> templateOrders) {
            this.templateOrders = templateOrders;
        }

        public List<Order> getOrdersByUserId(String templateUserId) {
            return templateOrders;
        }

        public void save(Order newOrder) {
            this.newOrder = newOrder;
        }

        public Order getNewOrder() {
            return newOrder;
        }
    }
}

标签: javajunitmockingmockitostubbing

解决方案


在您的场景中,我会考虑使用像 Mockito 这样的模拟框架。

一些主要优点:

  1. 向存储库接口添加新方法不需要在存根中实现它
  2. 支持精确次数和至少一次验证
  3. 允许按顺序进行灵活验证(例如:按您想要的顺序验证,而不是每次交互)
  4. 非常好的和简单的注解语法——@Mock、@InjectMocks、@Spy

这是一个示例-也许您会感兴趣:

// arrange
Warehouse mock = Mockito.mock(Warehouse.class);

//act
Order order = new Order(TALISKER, 50);
order.fill(warehouse); // fill will call remove() implicitly

// assert
Mockito.verify(warehouse).remove(TALISKER, 50); // verify that remove() method was actually called

推荐阅读