导致@ParameterizedTest失败Junit奇怪行为

vc6uscn9  于 2022-11-11  发布在  其他
关注(0)|答案(1)|浏览(139)

我有一个非常简单的测试用例,其中包含最基本的设置:

@Entity
public class Tags {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;

  @Column(unique = true)
  private String name;

  public Tags(String name) {
    this.name = name;
  }
}

@Repository
public interface TagsRepository extends JpaRepository<Tags, Integer> {}

试验装置:

@DataJpaTest
public class TagsTest implements WithAssertions {

  @Autowired
  private TagsRepository tagsRepo;

  @BeforeEach
  void setUp() {
    Tags tag1 = new Tags("tag1");
    Tags tag2 = new Tags("tag2");
    Tags tag3 = new Tags("tag3");

    tagsRepo.saveAll(List.of(tag1, tag2, tag3));
  }

  @AfterEach
  void cleanUp() {
    tagsRepo.deleteAll();
  }

  @Test
  void test() {
    Tags actual1 = tagsRepo.findById(1).orElse(null);
    assertThat(actual1).isNotNull();  // <- passed
  }

  @Test
  void test2() {
    Tags actual2 = tagsRepo.findById(1).orElse(null);
    assertThat(actual2).isNotNull();  // <- failed
  }

  @Test
  void test3() {
    Tags actual3 = tagsRepo.findById(2).orElse(null);
    assertThat(actual3).isNotNull();  // <- failed
  }
}

意外行为:

test class作为一个整体运行时,只有第一次测试通过,第二次和第三次测试均未通过。

这也导致了@ParameterizedTest中的问题:

@ParameterizedTest
@ValueSource(ints = { 1, 1, 2 }) // <- second and third test failed
void test4(Integer id) {
  Tags actual = tagsRepo.findById(id).orElse(null);
  assertThat(actual).isNotNull();
}

将dataSource更改为@MethodSource@CsvSource后的行为相同。

我尝试在每个测试中初始化数据,但发生了同样的事情:

@Test
void test() {
  Tags tag1 = new Tags("tag1");
  Tags tag2 = new Tags("tag2");
  Tags tag3 = new Tags("tag3");

  tagsRepo.saveAll(List.of(tag1, tag2, tag3));

  Tags actual1 = tagsRepo.findById(1).orElse(null);

  assertThat(actual1).isNotNull();

  tagsRepo.deleteAll();
}

为什么只有第一个测试通过而后续测试失败呢?我已经尝试使用不同的id组合传入。但都是相同的行为。
通过这个简单的演示,我得出了一个结论,运行类似的测试会导致问题,即使,测试不应该相互影响?
我知道我不应该测试SpringBoot提供的内置API,但这是我在使用@Parameterized测试带有多个参数的mybatis时发现的一个问题。
编辑:似乎大多数人都试图通过在每次测试前重新创建数据库来解决这个问题

voase2hg

voase2hg1#

它不起作用,因为每次在setUp()方法中删除/保存数据时,ID的计数器都会不断地增加:

@BeforeEach
  void setUp() {
    Tags tag1 = new Tags("tag1");
    Tags tag2 = new Tags("tag2");
    Tags tag3 = new Tags("tag3");

    tagsRepo.saveAll(List.of(tag1, tag2, tag3));
  }

对于第一个测试,您将拥有:

tag1-> id = 1
tag2-> id = 2
tag3-> id = 3

但对于第二个,您将获得:

tag1-> id = 4
tag2-> id = 5
tag3-> id = 6

等等...所以正确的方法是保存它们并保存在类级别的变量中,比如:

@DataJpaTest
public class TagsTest implements WithAssertions {

    @Autowired
    private TagsRepository tagsRepo;

    private Tags tag1;
    private Tags tag2;
    private Tags tag3;

    @BeforeEach
    void setUp() {
        tag1 = tagsRepo.save(new Tags("tag1"));
        tag2 = tagsRepo.save(new Tags("tag2"));
        tag3 = tagsRepo.save(new Tags("tag3"));
    }

    @AfterEach
    void cleanUp() {
        tagsRepo.deleteAll();
    }

    @Test
    void test() {
        Tags actual1 = tagsRepo.findById(tag1.getId()).orElse(null);
        assertThat(actual1).isNotNull();
    }

    @Test
    void test2() {
        Tags actual2 = tagsRepo.findById(tag1.getId()).orElse(null);
        assertThat(actual2).isNotNull();
    }

    @Test
    void test3() {
        Tags actual3 = tagsRepo.findById(tag2.getId()).orElse(null);
        assertThat(actual3).isNotNull();
    }
}

关于参数化测试,使用自动递增的id,您无法真正提前知道id

相关问题