【问题标题】:Unit test best practice in Spring boot for mocking on service levelSpring boot 中用于模拟服务级别的单元测试最佳实践
【发布时间】:2018-02-15 09:14:29
【问题描述】:

我们有一个单元测试,我们正在测试促销代码的兑换。 我们需要检查数据库中是否存在两个参数:Entity & User

在你将看到的代码中,

  1. 我们创建UserEntity 的实例
  2. 插入数据库(使用@Repository)
  3. 也创建一个 DTO ..etc

因为RedeemService 会调用UserEntity 服务来检查它们是否存在。

我觉得我们应该能够模拟(用户和实体服务),而不是做所有这些事情

这里是测试:

@Test 
    public void redeemPromoCodeTestValid() throws Exception {

        String userId = "OOUser";
        String fleetId = "F0001";
        String promoCodeId = "AFTER_CHRIS";

        User user = new User();
        user.setId(userId);
        user.setFleetId(fleetId);
        user.setUserName("OOabcdefg");
        userRepository.save(user);

        EntityX entity = new EntityX(); //EntityX, because Entity is a reserved keyword..
        entityRepository.save(entity);
        String entityId = entityRepository.findAll().get(0).getId();

        PromoCode promoCode = createPromoCode(promoCodeId);
        promoCodeRepository.save(promoCode);

        RedeemDTO add = new RedeemDTO();
        add.setUserId(userId);
        add.setEntityId(entityId);
        String jsonString = this.asJsonString(add);
        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.put("/billing/fleets/"+ fleetId + "/promoCodes/redeem/" + promoCodeId).content(jsonString).contentType(CONTENT_TYPE);

        mockMvcPromocode.perform(requestBuilder).andDo(print()).andExpect(status().isOk());

        List<Wallet> find = walletService.findWalletByEntityId(entityId);
        assertThat(find.size()).isEqualTo(1);
    }

我是 Spring Boot 和单元测试模拟的新手,因此非常感谢任何建议。

谢谢。

【问题讨论】:

    标签: spring unit-testing spring-boot mocking mockito


    【解决方案1】:

    不管单词的不同定义,有测试只测试你的一个类的代码(单元测试),测试测试 Spring 集成和 http 处理(集成测试),以及测试你的整个应用程序端到端测试结束(端到端测试)。目前尚不清楚您要编写哪种测试。

    如果要编写单元测试,则需要确定要测试的单元。如果要测试控制器,只测试Java类,不使用MockHttpServletRequestBuilder和SpringRunner。

    任何 Spring Class 也是一个普通的 Java 类,您可以像测试任何其他类一样对它们进行单元测试。但是,如果您使用构造函数注入,它会变得最简单:

    @Service
    class FooService {
    
        private final FooBean foo;
    
        @Autowired
        public FooService(FooBean foo) {
            this.foo = foo;
        }
    }
    
    public class FooServiceTest {
    
        @Test
        public void testFooService() {
            fooMock = mock(FooBean.class); // use Mockito or EasyMock, or real FooBean
            FooService fooService = new FooService(fooMock);
            // ...
        }
    }
    

    如果您想为控制器编写集成测试,请使用 MockHttpServletRequestBuilder 并模拟您的服务层。

    为此,请使用以下内容:

    @RunWith(SpringRunner.class)
    @ContextConfiguration(classes = {ControllerTestConfig.class})
    @WebAppConfiguration
    public class ControllerTest {
        ...
    }
    
    @Configuration
    public class ControllerTestConfig {
        @Bean
        public UserService userServiceMock() {
            ...
        }
    }
    

    对于端到端测试,不要使用模拟,但可能使用单独的 Spring 配置文件来连接到测试后端资源/内存数据库。

    【讨论】:

    • 因此问题是:是否可以仅使用单元测试来测试服务类?那怎么写呢?
    • 我加了一个例子
    猜你喜欢
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 2019-02-19
    • 1970-01-01
    相关资源
    最近更新 更多