gpt4 book ai didi

java - 如何模拟 bean 的某些方法调用,但在同一测试类中的其他方法调用中使用定义的 bean?

转载 作者:行者123 更新时间:2023-11-30 05:41:18 25 4
gpt4 key购买 nike

我正在尝试测试在测试配置中具有指定实现的服务接口(interface)。服务接口(interface)注入(inject) DAO 接口(interface),该接口(interface)在 TestConfiguration 中也有指定的实现。服务的实现被定义为将投入生产的实际服务,而测试 DAO 是接口(interface)的新的自定义实现。

在 95% 的情况下,我想使用测试 DAO 实现。然而,在某些测试中我想覆盖 DAO 的功能。由于我想要重写 DAO 的实例很少,所以我只想有条件地使用 Mockito 进行模拟,而不创建 DAO 接口(interface)的另一个实现(对于边缘情况,例如从 DAO 返回空列表)。理想情况下,它们应该位于专门用于测试服务的同一类中。

我尝试在测试类中的 DAO Bean 上使用 @Spy 注释。我尝试过在 DAO bean 上使用 @MockBean。我尝试过使用 Mockito 的 doReturn 和 when 功能来覆盖 DAO 的默认实现,但是,我总是从 TestConfiguration 中定义的 Test DAO 实现中获取结果。

我确实更改了我正在做的事情的文本,因为它是公司代码,但这正是我想要做的事情。

我的 TestConfiguration 是这样定义的

@TestConfiguration
public class TestAppConfiguration {

@Bean
public PersonService personService() {
return new PersonServiceImpl(personDao());
}

@Bean
public PersonDao personDao() {
return new TestPersonDaoImpl();
}
}

我的服务实现如下

public class PersonServiceImpl implements PersonService {
private Logger logger = LoggerFactory.getLogger(PersonServiceImpl.class);

private PersonDao personDao;

public PersonServiceImpl(PersonDao personDao){
this.personDao = personDao;
}

@Override
public List<PersonDto> getAllPersons() {
return personDao.findAll().stream()
.map(person -> PersonDtoFactory.getPersonDto(person))
.collect(Collectors.toList());
}

@Override
public PersonDto getPersonById(Long id) {
return PersonDtoFactory.getPersonDto(personDao.findById(id));

}
}

我的测试 DAO 实现如下

public class TestPersonDaoImpl implements PersonDao {

@Override
public List<PersonModel> findAll() {
return getPersons();
}

@Override
public List<PersonModel> findById(id) {
return getPersons().stream()
.filter(person -> person.getId() == id)
.collect(Collectors.toList());
}

private List<PersonModel> getPersons() {
List<PersonModel> personList = new ArrayList<>();
personList.add(new PersonModel(1L, "Susan");
personList.add(new PersonModel(2L, "Jerry");
personList.add(new PersonModel(3L, "Tom");
return personList;
}
}

最后是我的服务测试类

@RunWith(SpringRunner.class)
@Import(TestAppConfiguration.class)
public class PersonServiceTests {
//We won't test web socket functionality in this test class.
@Autowired
private PersonService personService;

@MockBean //want to overwrite in the test only when specified in the test, otherwise, use default TestPersonDaoImpl bean.
private PersonDao personDao;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}

@Test
public void getAllPersons() {
assert(personService.getAllTests().size() > 0);
}

@Test
public void getPersonById() {
assert(personService.getPersonById(1L).getName().equals("Susan"));
}

@Test
public void getAllPersons_NoPersons(){
//Mock the DAO call since it will have all of the test data by default
doReturn(new ArrayList<Person>()).when(personDao).findAll();
//when(personDao.findAll()).thenReturn(new ArrayList<>()); <-- this also doesn't work
assert(personService.getAllPersons().size() == 0);
}

预计所有测试都会通过,并且在服务实现中调用时 DAO 调用将被覆盖。实际结果是前两个测试通过,第三个测试失败,因为它没有覆盖dao调用。

最佳答案

使用@MockBean,您将获得一个注入(inject)的模拟实例。

使用@Spy,你的 dao 不会被注入(inject)到服务中

您需要@SpyBean..您将获得注入(inject)和调用的所有方法,因为它们是默认实现的。

关于java - 如何模拟 bean 的某些方法调用,但在同一测试类中的其他方法调用中使用定义的 bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55594342/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com