【问题标题】:Test method mockito with spring context带有弹簧上下文的测试方法模拟
【发布时间】:2018-11-16 23:04:05
【问题描述】:

您好,我有一种将人员添加到团队的方法。我想为此方法编写一个测试,但我是 junit/mockito 测试的新手,所以我有很多问题: 这是我的添加方法:

@Transactional
public void addPersonsToTeams(Long teamId, Long personId) {
    Assert.notNull(personId, "Object can't be null!");
    Assert.notNull(teamId, "Object can't be null!");
    try {
        Person person = personRepository.getOne(personId);
        Team team = teamRepository.getOne(teamId);
        person.getTeams().add(team);
        personRepository.save(person);
    } catch (Exception e) {
        throw new CreateEntityException();
    }

}

这两个实体(人/团队)之间存在关系 这是我的测试代码,但它不起作用:

@Test
    public void shouldAddPersonToTeam(){
        Team team = new Team(1l, "TestCase1", "Description1", "Krakow", 12);
        Person person = new Person(1L, "jan", "mucha", "krakow", "email1@onet.com", "Programing", "Developer");

        teamService.createTeam(mapper.map(team, TeamDto.class));
        personService.addPerson(mapper.map(person, PersonDto.class));

        teamService.addPersonsToTeams(team.getId(), person.getId());

        verify(teamRepository, times(1)).save(team);
        verify(personRepository, times(1)).save(person);


    }

模拟配置:

public class TeamServiceTest {
    private TeamService teamService;
    private ModelMapper mapper;
    private PersonService personService;

    @Mock
    private TeamRepository teamRepository;
    private PersonRepository personRepository; //-this is never assigned :/

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        this.mapper = new ModelMapper();
        teamService = new TeamService(teamRepository, this.mapper);
        personService = new PersonService(personRepository, this.mapper);

    }

【问题讨论】:

  • 错误是什么?
  • 测试不起作用
  • 你是如何实例化teamRepositorypersonRespository的?
  • @Mock private TeamRepository teamRepository;私人 PersonRepository personRepository;
  • @Before public void setUp() { MockitoAnnotations.initMocks(this); this.mapper = new ModelMapper(); teamService = new TeamService(teamRepository, this.mapper); personService = new PersonService(personRepository, this.mapper); }

标签: java unit-testing mocking


【解决方案1】:

你的问题是线条

Person person = personRepository.getOne(personId);
Team team = teamRepository.getOne(teamId);

在您正在测试的方法中。在addPersonsToTeams 的单元测试中,您不想测试两个getOne 方法的行为。这就是使用 Mockito 的全部意义所在——您可以为单个方法编写单元测试,而其他方法的行为不会影响测试。

这意味着您需要指定这两个调用将返回什么。这是对调用的“存根”,只有在调用方法的对象是间谍或模拟对象时才能这样做。所以在 Mockito 中,你可能会写类似

doReturn(myPerson).when(mockPersonRepository).getOne(personId);

这意味着无论何时调用mockPersonReposity.getOne(personId),都不会发生任何事情。方法本身没有运行,Mockito 只是立即返回myPerson

这就是你想要的技术。因此,当您向测试添加存根时,它可能看起来像这样。

@Mock private TeamRepository mockTeamRepository; 
@Mock private PersonRepository mockPersonRepository;

@Before 
public void setUp() { 
    MockitoAnnotations.initMocks(this); 
    mapper = new ModelMapper(); 
    teamService = new TeamService(mockTeamRepository, mapper); 
    personService = new PersonService(mockPersonRepository, mapper);
}

@Test
public void shouldAddPersonToTeam(){
    Team team = new Team(1L, "TestCase1", "Description1", "Krakow", 12);
    Person person = new Person(1L, "jan", "mucha", "krakow", "email1@onet.com", "Programing", "Developer");

    doReturn(team).when(mockTeamRepository).getOne(1L);
    doReturn(person).when(mockPersonRepository).getOne(1L);

    teamService.createTeam(mapper.map(team, TeamDto.class));
    personService.addPerson(mapper.map(person, PersonDto.class));

    teamService.addPersonsToTeams(team.getId(), person.getId());

    verify(mockTeamRepository).save(team);
    verify(mockPersonRepository).save(person);
}

只是加分。

  • 值得在模拟对象的变量名称上使用前缀 mock,以帮助跟踪哪些变量是模拟变量,哪些不是模拟变量。
  • 没有必要在您的verify 调用中写入times(1) - 默认验证模式是times(1),因此如果您将其省略,您的代码不会那么混乱。
  • 不要使用小写的l 作为long 文字 - 1l 看起来太像11。为了便于阅读,请始终使用大写字母L
  • Mockito 有另一种用于存根的语法,有时有效,但并非总是如此。它看起来像when(mockPersonRepository.getOne(personId)).thenReturn(person);。许多人发现这更具可读性,但它有很多缺点。我建议永远不要使用(实际上永远不要学习)这种其他语法。我的回答to this question 中概述了我这样做的原因。

【讨论】:

  • 感谢您的回答,但添加您的代码后,我有了这个;传递给 when() 的参数为空!正确存根的示例:doThrow(new RuntimeException()).when(mock).someMethod();此外,如果您使用 @Mock 注释,请不要错过 initMocks()
  • 好的,你确定你打电话给MockitoAnnotations.initMocks(this);吗?另外,PersonRepositoryTeamRepository 是否会被标记为 final?如果是这样,您将无法为它们创建模拟。
  • 这可能是错误的。我编辑我的帖子上部并向你展示我的模拟配置
  • PersonRepository 的声明前写上@Mock,正如我在回答中所展示的那样。
  • 天哪,当然是愚蠢的错误。但在此之后,我在创建团队对象时遇到问题:/ com.softwaremind.crew.common.CreateEntityException:创建新团队 - 失败。对象字段有错误
猜你喜欢
  • 1970-01-01
  • 2018-11-22
  • 2019-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多