Spring Mockito @BeforeAll 模拟逻辑仅适用于 1 个测试

Spring Mockito @BeforeAll mocking logic works on 1 test only

我无法理解为什么 @BeforeAll 中模拟的逻辑有效,但仅适用于第一次测试。 它们分别工作得很好,将相同的逻辑复制到两个测试将产生相同的结果——1 个通过,1 个失败。 发生了什么: in AboutUsService.update() 第一行出现错误在

pageRepository.getByName(ABOUT_US_PAGE).orElseThrow(null);

对于第一个测试,调用该方法会产生预期的结果,returns AboutUsPage 及其数据。但是对于下一个它会产生 Optional.empty 和 NullPointerException 最终。诀窍是什么,为什么模拟仅适用于一次测试? 另外,我检查了是否调用了真正的存储库,但似乎是其他原因造成的。 将注释更改为 @BeforeEach 可以解决这个问题,但它不应该与 @BeforeAll 一起工作吗? Spring 引导版本 2.3.4

@SpringBootTest(classes = {AboutUsService.class, AboutUsPageRepository.class,
    AboutUsPageImageStore.class, ImageUtil.class})
@TestInstance(Lifecycle.PER_CLASS)
public class AboutUsServiceTest {

  @Autowired
  private AboutUsService aboutUsService;

  @MockBean
  private AboutUsPageRepository pageRepository;

  @MockBean
  private AboutUsPageImageStore aboutUsPageImageStore;

  @MockBean
  private ImageUtil imageUtil;

  @BeforeAll
  public void configure() {
    when(pageRepository.getByName(anyString()))
        .thenReturn(Optional.of(AboutUsTestData.getAboutUsPage()));

    when(aboutUsPageImageStore.setContent(any(AboutUsPageImage.class), any(Resource.class)))
        .thenReturn(new AboutUsPageImage());
  }

  @Test
  public void updateWithImagesTest() {
    when(imageUtil.fileIsValid(any(MultipartFile.class)))
        .thenReturn(true);

    MultipartFile validFile = new MockMultipartFile("name", "etc", "content", "Hello".getBytes());
    aboutUsService.update(new MultipartFile[]{validFile});
    verify(pageRepository, times(1)).save(any(AboutUsPage.class));
  }

  @Test
  public void updateWithNoImagesTest() {
    AboutUsPage updated = aboutUsService.update(new MultipartFile[0]);
    AboutUsPage expected = AboutUsTestData.getAboutUsPage();
    assertSame(expected.getImages().size(), updated.getImages().size());
  }

}


@Service
@AllArgsConstructor
@Slf4j
public class AboutUsService {

  public static final String ABOUT_US_PAGE = "ABOUT_US_PAGE";

  private final AboutUsPageImageStore pageImageStore;
  private final ImageUtil imageUtil;
  private final AboutUsPageRepository pageRepository;

  @Transactional
  public AboutUsPage update(MultipartFile[] images) {
    AboutUsPage page = pageRepository.getByName(ABOUT_US_PAGE).orElseThrow(null);

    if (ArrayUtils.isNotEmpty(images)) {
      List<AboutUsPageImage> pageImages = new ArrayList<>();
      Arrays.stream(images).forEach(extraImage -> {
        if (imageUtil.fileIsValid(extraImage)) {
          AboutUsPageImage infoImage = new AboutUsPageImage();
          pageImageStore.setContent(infoImage, extraImage.getResource());
          infoImage.setPage(page);
          pageImages.add(infoImage);
        }
      });

      if (CollectionUtils.isNotEmpty(pageImages)) {
        page.setImages(pageImages);
      }
      return pageRepository.save(page);

    } else {
      return page;
    }
  }
}


@Repository
public interface AboutUsPageRepository extends JpaRepository<AboutUsPage, Long> {

  Optional<AboutUsPage> getByName(String name);

}

@BeforeAll 在执行任何测试之前执行一次。如果您需要在每次测试之前执行的逻辑,请使用 @Before