JUnit 5无法模拟从被测函数调用的函数

问题描述 投票:0回答:2

我是Junit 5的新手。被测类中有两个函数,第一个函数调用第二个函数,第二个函数返回一个值,该值在第一个函数中进行处理。因此,我为此类创建了一个模拟程序,但是当我测试第一个函数时,无法模拟第二个函数调用。

第一个函数--exportOpportunityListing()第二个功能-entityToCsvReport()

public class OpportunityReportServiceImpl extends BaseService implements OpportunityReportService {

    @Value("${nfs.mountPath}")
    private String fileMountPath;

    @Value("${take1.url.host}")
    private String take1HostURL;

    @Autowired
    UsersRepository usersRepository;

    @Autowired
    MailUtil mailUtil;

    @Autowired
    OpportunityJDBCRepository ojdbc;

    @Override
    @Async
    public void exportOpportunityListing(Map<String, Object> paramMap, List<OpportunityCriteria> lfvo,
            String xRemoteUser) {
        try {
            List<OpportunityJDBCDTO> lo = ojdbc.getOppListWithoutPagination(paramMap, lfvo);
            List<OpportunityReport> exportData = lo.parallelStream().map(this::entityToCsvReport)
                    .collect(Collectors.toList());
            CsvCustomMappingStrategy<OpportunityReport> mappingStrategy = new CsvCustomMappingStrategy<>();
            mappingStrategy.setType(OpportunityReport.class);
            String dirPath = fileMountPath + REPORT_PATH;
            File fileDir = new File(dirPath);
            if (!fileDir.exists()) {
                FileUtils.forceMkdir(fileDir);
            }
            String pathWithoutExtension = dirPath + "opportunity_data_"
                    + LocalDateTime.now().format(DateTimeFormatter.ofPattern(YYYYMMDDHHMMSS));
            File reportFile = new File(pathWithoutExtension + EXTENSION_CSV);
            Writer writer = new PrintWriter(reportFile);
            StatefulBeanToCsv<OpportunityReport> beanToCsv = new StatefulBeanToCsvBuilder<OpportunityReport>(writer)
                    .withMappingStrategy(mappingStrategy).build();
            beanToCsv.write(exportData);
            writer.close();
            String zipFilePath = pathWithoutExtension + EXTENSION_ZIP;
            ZipUtil.zip(reportFile, zipFilePath);
            Users remoteUser = usersRepository.findByUsername(xRemoteUser)
                    .orElseThrow(() -> new Take1Exception(ErrorMessage.USER_NOT_FOUND_WITH_USERNAME, xRemoteUser));
            Mail mail = Mail.builder().to(new String[] { remoteUser.getEmail() })
                    .model(MailModel.builder().name(remoteUser.getName())
                            .body("Please find attached the opportunity report you requested.").build())
                    .subject("Opportunity Report").attachments(Arrays.asList(new File(zipFilePath))).build();
            mailUtil.sendMail(mail);
            Files.delete(reportFile.toPath());
        } catch (IOException | CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
            throw new Take1Exception(ErrorMessage.INTERNAL_SERVER_EXCEPTION, e);
        }

    }

    public OpportunityReport entityToCsvReport(OpportunityJDBCDTO o) {
        OpportunityReport or = modelMapper.map(o, OpportunityReport.class);
        or.setCurrency("USD");
        or.setOnline(Boolean.TRUE.equals(o.getIsOnline()) ? "YES" : "NO");
        return or;
    }

}

这是我的JUnit测试用例。

class OpportunityReportServiceImplTest {

    @InjectMocks
    OpportunityReportServiceImpl opportunityReportServiceImpl;

    @Autowired
    OpportunityReportServiceImpl ors;

    @Mock
    OpportunityJDBCRepository ojdbc;

    @Mock
    UsersRepository usersRepository;

    @Mock
    MailUtil mailUtil;

    @Mock
    ModelMapper mp;

    String username = "anandabhishe";
    String nfusername = "ananda";
    Mail mail;
    List<OpportunityJDBCDTO> lo = new ArrayList<OpportunityJDBCDTO>();
    List<OpportunityReport> lor = new ArrayList<OpportunityReport>();

    @BeforeEach
    void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        ReflectionTestUtils.setField(opportunityReportServiceImpl, "fileMountPath", ".");
        ReflectionTestUtils.setField(opportunityReportServiceImpl, "take1HostURL", "");
        lo.add(new OpportunityJDBCDTO());
        lor.add(new OpportunityReport());

    }

    @Test
    void testExportOpportunityListing() throws IOException {
        OpportunityReport or = new OpportunityReport();
        or.setCurrency("USD");
        or.setOnline("Yes");

        when(ojdbc.getOppListWithoutPagination(getParamMap(), getOppCriteria())).thenReturn(lo);
        when(usersRepository.findByUsername(username)).thenReturn(Optional.of(getUser()));
        doNothing().when(mailUtil).sendMail(mail);
        // doNothing().when(opportunityReportServiceImpl).entityToCsvReport(oj);
        when(opportunityReportServiceImpl.entityToCsvReport(getOpportunityJDBCDTO())).thenReturn(or);
        opportunityReportServiceImpl.exportOpportunityListing(getParamMap(), getOppCriteria(), username);
        assertTrue(true);
        FileUtils.forceDelete(new File("." + REPORT_PATH));
    }

    private Map<String, Object> getParamMap() {
        return new HashMap<String, Object>();
    }

    private List<OpportunityCriteria> getOppCriteria() {
        List<OpportunityCriteria> loc = new ArrayList<>();
        loc.add(new OpportunityCriteria());
        return loc;
    }

    private OpportunityJDBCDTO getOpportunityJDBCDTO() {
        OpportunityJDBCDTO oj = new OpportunityJDBCDTO();
        oj.setIsOnline(true);
        oj.setApplicationCount(2);
        oj.setCost(200);
        oj.setCountryCode("in");
        oj.setCreationDate(LocalDateTime.now());
        oj.setEndDate(LocalDate.now());
        oj.setLocation("test");
        oj.setOpportunityId(123);
        oj.setOpportunityStatus("test");
        oj.setOpportunityStatusId(1);
        oj.setOpportunityTitle("test");
        oj.setOpportunityType("test");
        oj.setOpportunityTypeColor("test");
        oj.setOpportunityTypeId(1);
        oj.setPublishedAt(LocalDateTime.now());
        oj.setPublishedBy("test");
        oj.setPublishedByUserName("test");
        oj.setRegistrationUrl("test");
        oj.setStartDate(LocalDate.now());
        oj.setSummary("test");
        oj.setUserEmail("test");
        oj.setUserFullName("test");
        oj.setUserId(1);
        oj.setUserName("test");
        oj.setVendorName("test");
        return oj;
    }

    private Users getUser() {
        Users user = new Users();
        return user;
    }

}

当调用Test类中的行时,我得到了Null Pointer Exception:

when(opportunityReportServiceImpl.entityToCsvReport(getOpportunityJDBCDTO())).thenReturn(or);
java junit5 spring-test
2个回答
0
投票

我缺少了对第二个函数中使用的modelmapper存根的嘲笑,添加完之后,测试通过了。

OpportunityReport or = new OpportunityReport();
        OpportunityJDBCDTO oj = new OpportunityJDBCDTO();
        when(ojdbc.getOppListWithoutPagination(any(HashMap.class), anyList())).thenReturn(lo);
        when(usersRepository.findByUsername(anyString())).thenReturn(Optional.of(getUser()));
        doNothing().when(mailUtil).sendMail(mail);
        doReturn(or).when(mp).map(oj, OpportunityReport.class);
        opportunityReportServiceImpl.exportOpportunityListing(getParamMap(), getOppCriteria(), username);
        assertTrue(true);

0
投票

之所以这样,是因为opportunityReportServiceImpl不是模拟对象-它是您要测试的对象,但是您想像对待模拟对象一样对它的方法进行存根。

我建议您不要尝试对要测试的对象的方法进行存根。但是,如果需要,则需要将其声明为@Spy。然后存根,您需要doReturn/when语法而不是when/thenReturn。可能看起来像

doReturn(lo).when(ojdbc).getOppListWithoutPagination(getParamMap(), getOppCriteria());

-2
投票

我认为问题出在

 when(ojdbc.getOppListWithoutPagination(getParamMap(), getOppCriteria())).thenReturn(lo);

private Map<String, Object> getParamMap() {
    return new HashMap<String, Object>();
}

尝试按如下所示进行更新。

 when(ojdbc.getOppListWithoutPagination(any(HashMap.class), any(OpportunityJDBCDTO.class))).thenReturn(lo);

每次创建新对象,这都应该引起问题

类似地,第三个参数-OpportunityJDBCDTO

© www.soinside.com 2019 - 2024. All rights reserved.