Как я могу утверждать значение, созданное в методе void? - PullRequest
2 голосов
/ 28 января 2020

У меня есть класс

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.

Я создаю этот тест. Я создаю удары для каждого хранилища и сохраняю сохраненный объект в эту заглушку. И я добавляю дополнительный метод для получения этого объекта для утверждения. Оно работает. Но у меня есть 2 проблемы:

  1. Мой объект шаблона изменчив. Это не большая проблема, но это факт.
  2. Если я добавляю новые методы в интерфейс репозитория, я должен реализовать его в заглушках.

Вопрос: Как я могу тестировать клонированный объекты, подобные тезисам из моего примера?

Я не использую 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;
        }
    }
}

1 Ответ

0 голосов
/ 28 января 2020

В вашем сценарии я бы рассмотрел использование фреймворка Mockito.

Некоторые основные преимущества:

  1. Добавление новых методов в интерфейс хранилища не требует его реализации в заглушках
  2. Поддерживает точное число- of of times и, по крайней мере, однократная проверка
  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
...