【问题标题】:Not able to save data in H2 Database using SpringBootTest and Spring JPA Repository无法使用 SpringBootTest 和 Spring JPA Repository 在 H2 数据库中保存数据
【发布时间】:2020-07-22 01:16:55
【问题描述】:

我正在使用@SpringBootTest 测试 SpringSecurity 基本身份验证。当我测试它时,h2 数据库不保存数据。我在控制台中没有看到插入语句,我显然在运行我的实际 SpringBoot 时看到了应用程序并从前端插入数据。请帮忙。

下面是我的测试:

        @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
        @ContextConfiguration(classes=ConnectionsAppApplication.class)
        @Transactional
        public class AuthenticationTest {

            @Autowired
            private WebApplicationContext context;

            private MockMvc mockMvc;

            @Mock
            CustDetailsRepository custRepository;

            @Mock
            BCryptPasswordEncoder encrypt;

            @InjectMocks
            CustomerServiceImpl customerServiceImpl;



           @BeforeEach
           public void setup() {

             MockitoAnnotations.initMocks(this);
             mockMvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity())
                .build();
           }


          @Test
          void testAuthentication() {

              CustomerDetails customer = new CustomerDetails();
              customer.setEmailid("abc.com");
              customer.setPassword("abc@123456");
              customerServiceImpl.saveUser(customer);
           try {
               this.mockMvc.perform(get("/api/login")
               .with(httpBasic("abc.com","abc@123456")))
               .andDo(print())
               .andExpect(status().isOk())
               .andReturn();
           } catch (Exception e) {
                e.printStackTrace();
            }
         }

       }

CustomerServiceImpl 类中的 saveUser 方法:

        public void saveUser(CustomerDetails customerDetails) {
          customerDetails.setPassword(bCryptPasswordEncoder.encode(customerDetails.getPassword()));
          custDetailsRepository.save(customerDetails);
         }

【问题讨论】:

  • 您正在模拟您的存储库。你怎么能期望任何东西都保存在数据库中?
  • @Lesiak 我做错了吗?你能纠正我吗?模拟 SpringJPA 存储库如何无法保存数据。
  • Mock 是一个虚拟对象,您使用它而不是真正的实现来简化您的测试 - 您告诉它将调用什么方法以及回答什么(如果没有设置期望,Mockito 默认回答 null )。如果您在模拟上调用custDetailsRepository.save,则不会调用数据库。现在由您决定是否要在测试中使用 h2 或模拟存储库。不错的 mockito 教程:baeldung.com/mockito-series
  • 我将我的服务 customerServiceImpl 转换为 @autowired(集成测试),现在我可以通过测试了。但是,我将检查如何使用 mockito 进行测试,非常感谢这个答案。它帮助了我:)。
  • 请注意,如果你想用 SpringBootTest 中的 Mock 替换测试中的某些真实 Bean,则需要使用 @MockBean 注释(而不是 @Mock)。另外,不要使用@InjectMocks 注释。

标签: spring database spring-security mockito spring-boot-test


【解决方案1】:

您有 2 个选项来实施此测试:

选项 1:使用真正的 h2

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes=ConnectionsAppApplication.class)
@Transactional
public class AuthenticationTest {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

    @Autowired
    CustomerServiceImpl customerServiceImpl;

    @BeforeEach
    public void setup() {

        mockMvc = MockMvcBuilders
            .webAppContextSetup(context)
            .apply(springSecurity())
            .build();
    }


    @Test
    void testAuthentication() {

        CustomerDetails customer = new CustomerDetails();
        customer.setEmailid("abc.com");
        customer.setPassword("abc@123456");
        customerServiceImpl.saveUser(customer);
        try {
             this.mockMvc.perform(get("/api/login")
                 .with(httpBasic("abc.com","abc@123456")))
                 .andDo(print())
                 .andExpect(status().isOk())
                 .andReturn();
         } catch (Exception e) {
             e.printStackTrace();
         }
    }
}

选项 2:模拟您的服务/存储库

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes=ConnectionsAppApplication.class)
@Transactional
public class AuthenticationTest {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

    @MockBean
    CustomerServiceImpl customerServiceImpl;

    @BeforeEach
    public void setup() {
        mockMvc = MockMvcBuilders
            .webAppContextSetup(context)
            .apply(springSecurity())
            .build();
    }


    @Test
    void testAuthentication() {
        // set expectations on CustomerServiceImpl
        CustomerDetails customer = new CustomerDetails();
        customer.setEmailid("abc.com");
        customer.setPassword("abc@123456");
        // mock the method you use to fetch the customer
        when(customerServiceImpl.getUser("abc.com").thenReturn(customer);
        try {
            this.mockMvc.perform(get("/api/login")
                .with(httpBasic("abc.com","abc@123456")))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();
           } catch (Exception e) {
                e.printStackTrace();
           }
      }
}

请注意,您也可以使用@WebMvcTest 仅测试应用程序的 Web 切片(这意味着不会实例化其他 bean,例如您在控制器中依赖的所有 sercies 必须由 @MockBean 交付)

【讨论】:

  • 我用的是第一个。谢谢。
猜你喜欢
  • 1970-01-01
  • 2019-03-31
  • 1970-01-01
  • 2021-12-01
  • 2020-08-12
  • 2022-01-07
  • 2021-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多