关于最佳实践的Spring Boot单元测试和currectli写作测试

时间:2018-07-06 10:18:51

标签: java unit-testing mockito spring-boot-test

我想在我的项目中开始编写单元测试。我尝试过多次。他总是辞职,因为他听不懂意思。因为我无法找到知识并将其形成一个整体。我读了很多文章,看了很多例子,它们都是不同的。结果,我了解了为什么需要编写测试,了解了如何编写测试,但是我不了解如何正确地编写测试。而且我不知道如何编写它们以便使它们有用。我有一些问题:

例如,我有服务:

@Service
public class HumanServiceImpl implements HumanService {

  private final HumanRepository humanRepository;

  @Autowired
  public HumanServiceImpl(HumanRepository humanRepository) {
    this.humanRepository = humanRepository;
  }

  @Override
  public Human getOneHumanById(Long id) {
    return humanRepository.getOne(id);
  }

  @Override
  public Human getOneHumanByName(String firstName) {
    return humanRepository.findOneByFirstName(firstName);
  }

  @Override
  public Human getOneHumanRandom() {
    Human human = new Human();
    human.setId(Long.parseLong(String.valueOf(new Random(100))));
    human.setFirstName("firstName"+ System.currentTimeMillis());
    human.setLastName("LastName"+ System.currentTimeMillis());
    human.setAge(12);//any logic for create Human
    return human;
  }
}

我尝试为此服务编写单元测试:

@RunWith(SpringRunner.class)
public class HumanServiceImplTest {

  @MockBean(name="mokHumanRepository")
  private HumanRepository humanRepository;

  @MockBean(name = "mockHumanService")
  private HumanService humanService;

  @Before
  public void setup() {
    Human human = new Human();
    human.setId(1L);
    human.setFirstName("Bill");
    human.setLastName("Gates");
    human.setAge(50);

    when(humanRepository.getOne(1L)).thenReturn(human);
    when(humanRepository.findOneByFirstName("Bill")).thenReturn(human);
  }

  @Test
  public void getOneHumanById() {
    Human found = humanService.getOneHumanById(1L);
    assertThat(found.getFirstName()).isEqualTo("Bill");
  }

  @Test
  public void getOneHumanByName() {
    Human found = humanService.getOneHumanByName("Bill");
    assertThat(found.getFirstName()).isEqualTo("Bill");
  }

  @Test
  public void getOneHumanRandom() {
    //???
  }
}

我有问题:

1。我应该在哪里填充物体?我看到了不同的实现方式

@Before中,就像在我的示例中,在@Test中,混合实现-当人类在@Before中创建并表达

when(humanRepository.getOne(1L)).thenReturn(human); 

@Test方法中

  private Human human;

  @Before
  public void setup() {
    human = new Human();
    ...
  }

  @Test
  public void getOneHumanById() {
    when(humanRepository.getOne(1L)).thenReturn(human);
    Human found = humanService.getOneHumanById(1L);
    assertThat(found.getFirstName()).isEqualTo("Bill");
  }

2。如何测试getOneHumanRandom()方法?

服务在调用此方法时不使用存储库。我可以使该方法成为模拟方法,但是它将带来什么?

when(humanService.getOneHumanRandom()).thenReturn(human);
...
@Test
  public void getOneHumanRandom() {
    Human found = humanService.getOneHumanRandom();
    assertThat(found.getFirstName()).isEqualTo("Bill");
  }

我只是从测试类中的服务中复制逻辑。这样的测试有什么意义,有必要吗?

1 个答案:

答案 0 :(得分:0)

1。我应该在哪里填充物体?我看到了不同的实现方式

我将在所有/大多数测试之间使用@Before进行任何常见设置。任何特定于特定测试的设置都应纳入该测试方法。如果某些(而非全部)测试之间存在通用设置,则可以编写专用设置方法。

请记住使您的测试/代码保持干燥(不要重复!)。测试有一个维护因素,将通用代码保持在一起,有助于减轻将来的麻烦。

2。如何测试getOneHumanRandom()方法?

您应该创建一个Human toString()方法。此方法应合并Human对象上的所有属性。您可以调用getOneHumanRandom()两次,并断言它们不相等。

@Test
public void getOneHumanRandomTest()
{
    // SETUP / TEST
    Human one = service.getOneHumanRandom();
    Human two = service.getOneHumanRandom();
    // VERIFY / ASSERT
    assertNotEquals("these two objects should not be equal", one.toString(), two.toString())
}

希望这会有所帮助!