java - 如何断言在 void 方法中创建的值?

标签 java junit mocking mockito stubbing

我有课

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,并将保存的对象存储到这个 stub 中。我添加了额外的方法来获取这个对象的断言。
有用。但我有两个问题:
  • 我的模板对象是可变的。这不是一个大问题,但这是一个事实。
  • 如果我向存储库接口(interface)添加新方法,我必须在 stub 中实现它。

  • 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;
            }
        }
    }
    

    最佳答案

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

    一些主要优点:

  • 向存储库接口(interface)添加新方法不需要在 stub 中实现它
  • 支持精确次数和至少一次验证
  • 允许按顺序进行灵活验证(例如:按您想要的顺序验证,而不是每次交互)
  • 非常漂亮和简单的注释语法 - @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
    

    关于java - 如何断言在 void 方法中创建的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59950635/

    相关文章:

    java - 用于 IntelliJ IDEA 的 OpenJDK 或 Sun Java

    java - Spring MVC RestController 不明确的 PathVariable 映射

    java - 使用 JPA 和 JUnit 测试时如何一致地删除内存数据库中的 H2

    grails - 仅在集成测试中需要模拟一种服务方法

    java - sh 文件 NoClassDefFoundError

    java - POST 数据未通过 HttpURLConnection 发送

    java - 在 jmockit 中模拟被测类的私有(private)方法

    java - Axon 夹具注入(inject)在 @CommandHandler 注解的方法中失败(构造函数除外)

    mocking - 通过 websphere mq 模拟外部系统

    node.js - 模拟 Typeorm QueryBuilder