junit 使用ID与AssertJ进行比较是个好主意吗?

brjng4g3  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(119)

我得到了下面的类,我想用它来测试我的存储库:

package de.gabriel.vertretungsplan.repositories;

import de.gabriel.vertretungsplan.models.Fach;
import de.gabriel.vertretungsplan.models.Klasse;
import de.gabriel.vertretungsplan.models.StundenplanEintrag;
import de.gabriel.vertretungsplan.models.Tag;
import de.gabriel.vertretungsplan.models.enums.Anwesenheit;
import de.gabriel.vertretungsplan.models.enums.Rolle;
import de.gabriel.vertretungsplan.models.enums.Tage;
import de.gabriel.vertretungsplan.models.users.Lehrer;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;

import java.util.List;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

@DataJpaTest
@ActiveProfiles("test")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class StundenplanEintragRepositoryTest {

    @Autowired
    private StundenplanEintragRepository stundenplanEintragRepository;
    @Autowired
    private KlasseRepository klasseRepository;
    @Autowired
    private FachRepository fachRepository;
    @Autowired
    private LehrerRepository lehrerRepository;
    @Autowired
    private TagRepository tagRepository;

    private Lehrer deutschLehrer;
    private Tag montag;
    private StundenplanEintrag stundenplanEintragReference;

    @BeforeAll
    void init() {
        Klasse klasse6a = new Klasse("6a");

        klasseRepository.saveAll(List.of(
                klasse6a
        ));

        Fach deutsch = new Fach("Deutsch", "DE");

        fachRepository.saveAll(List.of(
                deutsch
        ));

        deutschLehrer = new Lehrer("deutschLehrer", "deutschLehrer", Rolle.getPrefixedRolle(Rolle.LEHRER), Anwesenheit.ANWESEND);
        deutschLehrer.setFaecher(List.of(deutsch));

        lehrerRepository.saveAll(List.of(
                deutschLehrer
        ));

        montag = new Tag(Tage.MONTAG);

        tagRepository.saveAll(List.of(
                montag
        ));

        stundenplanEintragReference = new StundenplanEintrag(1, klasse6a, deutsch, deutschLehrer, montag);

        stundenplanEintragRepository.saveAll(List.of(
                stundenplanEintragReference
        ));
    }

    @AfterAll
    void tearDown() {
        stundenplanEintragRepository.deleteAll();
    }

    @Test
    @DisplayName("Check if correct Stundenplan Eintrag is returned given Lehrer [deutschLehrer] and Tag [montag]")
    void findByLehrerAndTag() {
        List<StundenplanEintrag> stundenplanEintrag = stundenplanEintragRepository.findByLehrerAndTag(deutschLehrer, montag);
        assertThat(stundenplanEintrag.get(0).getId()).isEqualTo(stundenplanEintragReference.getId());
    }

    @Test
    @DisplayName("Check if correct Stundenplan Eintrag is returned given Lehrer [deutschLehrer]")
    void findByLehrer() {
        List<StundenplanEintrag> stundenplanEintrag = stundenplanEintragRepository.findByLehrer(deutschLehrer);
        assertThat(stundenplanEintrag.get(0).getLehrer().getUsername()).isEqualTo(deutschLehrer.getUsername());
    }

}

字符串
正如你所看到的,我正在通过一个字段将来自仓库的结果与引用对象(如idusername)进行比较,因为如果我像这样比较它们:

@Test
    @DisplayName("Check if correct Stundenplan Eintrag is returned given Lehrer [deutschLehrer] and Tag [montag]")
    void findByLehrerAndTag() {
        List<StundenplanEintrag> stundenplanEintrag = stundenplanEintragRepository.findByLehrerAndTag(deutschLehrer, montag);
        assertThat(stundenplanEintrag.get(0)).isEqualTo(stundenplanEintragReference);
    }

    @Test
    @DisplayName("Check if correct Stundenplan Eintrag is returned given Lehrer [deutschLehrer]")
    void findByLehrer() {
        List<StundenplanEintrag> stundenplanEintrag = stundenplanEintragRepository.findByLehrer(deutschLehrer);
        assertThat(stundenplanEintrag.get(0).getLehrer()).isEqualTo(deutschLehrer);
    }


测试失败是因为实际对象的地址与“预期”对象的地址不同,即使它们是“相同的”对象。

Expected :de.gabriel.vertretungsplan.models.StundenplanEintrag@38d895e8
Actual   :de.gabriel.vertretungsplan.models.StundenplanEintrag@1b897ffb


我知道它在内存中得到了一个新的地址(如评论中所指出的错误,它是哈希码)。我想知道用id之类的东西进行比较是否是一种好的做法,或者你会如何解决这个问题,或者是否有更好的做法来比较存储库返回的对象与原始保存的对象?(我仍然希望在@BeforeAll注解方法中只保存一次实体)

quhf5bfb

quhf5bfb1#

一般来说,我在测试中的比较ID中没有看到任何不好的东西。很明显,您操作记录并Assert它是否是相同的记录(相同的记录具有相同的ID)。
当然,作为一种选择,你可以考虑让你的解决方案更复杂,覆盖你的类的equals()(和hashCode())方法。它将使解决方案更加优雅,因此您在类中封装了“相同”的定义。您可以定义需要相等的字段,以便将对象视为相等。
我不认为你的问题有一个“正确”的答案。看情况查看Internet上的讨论,了解在哪些情况下需要重写equals,哪些情况下不需要。下面是这样的一对夫妇的讨论:

  1. https://softwareengineering.stackexchange.com/questions/399265/do-we-always-need-to-override-equals-hashcode-when-crreating-a-new-class
  2. Why do I need to override the equals and hashCode methods in Java?
    正如我所说的,一开始,我可能会比较ID,而不是走覆盖的道路,特别是如果你对此没有信心的话。
slmsl1lt

slmsl1lt2#

在您的案例中没有最佳实践,您应该考虑业务逻辑自行定义比较规则。我想强调的唯一相关实践是使用测试名称,以便它们反映测试的实际给定/when/then部分。

相关问题