我正在尝试测试在TestConfiguration中具有指定实现的服务接口。服务接口将注入DAO接口,该接口在TestConfiguration中也具有指定的实现。服务的实现定义为将在生产中使用的实际服务,而测试DAO是该接口的新的自定义实现。
在95%的情况下,我想使用Test DAO实施。但是,在某些测试中,我想覆盖DAO的功能。由于我想重写DAO的实例很少,因此我只想在有条件的情况下使用Mockito进行模拟,而无需创建DAO接口的另一种实现(对于从DAO返回空列表等极端情况)。理想情况下,它们应该在专门用于测试服务的类中。
我尝试在Test类的DAO Bean上使用@Spy批注。我尝试在DAO bean上使用@MockBean。我尝试使用Mockito的doReturn以及何时使用功能覆盖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 ApuMonitoringServiceTests {
//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<Apu>()).when(personDao).findAll();
//when(personDao.findAll()).thenReturn(new ArrayList<>()); <-- this also doesn't work
assert(personService.getAllPersons().size() == 0);
}
预期所有测试都会通过,并且在服务实现中调用DAO调用时将被覆盖。实际结果是前两个测试通过了,而第三个测试失败了,因为它没有覆盖dao调用。
答案 0 :(得分:1)
使用@MockBean
,您将获得一个注入的模拟实例。
使用@Spy
,您的dao将不会被注入服务
您需要@SpyBean
..您将获得注入以及默认情况下实现的所有方法的调用。