当前位置: 首页 > 知识库问答 >
问题:

Spring Boot maven多模块项目-单元测试(应用程序上下文)

宰父焕
2023-03-14
    null
    null
@RunWith(SpringRunner.class)
public class DeviceRepositoryServiceTest {

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @MockBean
    private DeviceRepository deviceRepository;

    @Autowired
    private DeviceMapper deviceMapper;

    private DeviceRepositoryService deviceRepositoryService;

    private final String imei = "123456789123456";
    private final String producer = "samsung";
    private final String model = "s5";

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        deviceRepositoryService = new DeviceRepositoryService(deviceRepository, deviceMapper);
    }

    @org.springframework.boot.test.context.TestConfiguration
    static class TestConfiguration {
        @Bean
        public DeviceMapper deviceMapper() {
            return new DeviceMapperImpl();
        }
    }

    @Test
    public void test_should_create_device() {
        given(deviceRepository.findByImei(imei)).willReturn(null);
        when(deviceRepository.save(any(Device.class))).thenAnswer((Answer) invocation -> invocation.getArguments()[0]);
        DeviceSnapshot device = deviceRepositoryService.createOrFindDeviceByImei(imei, producer, model);
        assertThat(device.getImei()).isEqualTo(imei);
        assertThat(device.getProducer()).isEqualTo(producer);
        assertThat(device.getModel()).isEqualTo(model);
        verify(deviceRepository, times(1)).save(any(Device.class));
    }

    @Test
    public void test_should_return_device() {
        Device testDevice = createTestDevice();
        given(deviceRepository.findByImei(imei)).willReturn(testDevice);
        DeviceSnapshot actualDevice = deviceRepositoryService
                .createOrFindDeviceByImei(testDevice.getImei(), testDevice.getProducer(), testDevice.getModel());
        assertThat(actualDevice.getImei()).isEqualTo(testDevice.getImei());
        assertThat(actualDevice.getProducer()).isEqualTo(testDevice.getProducer());
        assertThat(actualDevice.getModel()).isEqualTo(testDevice.getModel());
        verify(deviceRepository, times(0)).save(any(Device.class));
        verify(deviceRepository, times(1)).findByImei(testDevice.getImei());
    }

    @Test
    public void test_should_find_device() {
        Device device = createTestDevice();
        given(deviceRepository.findOne(device.getId())).willReturn(device);
        DeviceSnapshot actualDevice = deviceRepositoryService.findDeviceById(device.getId());
        DeviceSnapshot expectedDevice = deviceMapper.toDeviceSnapshot(device);
        assertThat(actualDevice).isEqualTo(expectedDevice);
        verify(deviceRepository, times(1)).findOne(device.getId());
    }

    @Test
    public void test_should_find_device_by_pparams() {
        Device device = createTestDevice();
        Long proposalId = 1L, providerConfigId = 2L;
        given(deviceRepository.findByProposalParams(proposalId, providerConfigId)).willReturn(device);
        DeviceSnapshot actualDevice = deviceRepositoryService.findDeviceByProposalParams(proposalId, providerConfigId);
        DeviceSnapshot expectedDevice = deviceMapper.toDeviceSnapshot(device);
        assertThat(actualDevice).isEqualTo(expectedDevice);
        verify(deviceRepository, times(1)).findByProposalParams(proposalId, providerConfigId);
    }

    @Test
    public void test_should_throw_not_found_1() {
        given(deviceRepository.findOne(anyLong())).willReturn(null);
        this.thrown.expect(DeviceNotFoundException.class);
        deviceRepositoryService.findDeviceById(1L);
    }

    @Test
    public void test_should_throw_not_found_2() {
        given(deviceRepository.findByProposalParams(anyLong(), anyLong())).willReturn(null);
        this.thrown.expect(DeviceNotFoundException.class);
        deviceRepositoryService.findDeviceByProposalParams(1L, 1L);
    }

    private Device createTestDevice() {
        return Device.builder()
                .id(1L)
                .imei(imei)
                .model(model)
                .producer(producer)
                .build();
    }
}
@Slf4j
@Service
@AllArgsConstructor
@Transactional
public class ProposalRepositoryService implements ProposalService {

    private final ProposalRepository proposalRepository;
    private final ProposalMapper proposalMapper;
    private final ProposalRepositoryProperties repositoryProperties;
    private final ImageProposalRepository imageProposalRepository;
    private final ProviderConfigService providerConfigService;
    ...
}

在上面的类中有更多的依赖项,问题是我不想为每个测试编写大量的配置代码(TestConfiguration注释)。例如,如果我向某个服务添加一些依赖项,我将不得不更改一半的单元测试类,而且许多代码会重复出现。我还举了一个例子,当单元测试代码因为配置定义而变得丑陋时:

@TestPropertySource("classpath:application-test.properties")
public class RemoteReportProcessorRepositoryServiceTest {

    @Autowired
    private RemoteReportProcessorRepositoryService remoteReportProcessorRepositoryService;

    @TestConfiguration //here, I don't want to write bunch of configuration code for every test
    static class TestConfig {

        @Bean
        @Autowired
        public RemoteReportProcessorRepositoryService remoteReportProcessorRepositoryService(RemoteReportMailService remoteReportMailService,
                                                                                             FtpsService ftpsService,
                                                                                             RemoteDailyReportProperties remoteDailyReportProperties,
                                                                                             RemoteMonthlyReportProperties remoteMonthlyReportProperties,
                                                                                             DeviceRepository deviceRepository,
                                                                                             ProposalRepository proposalRepository) {
            return new RemoteReportProcessorRepositoryService(ftpsService, remoteReportMailService, remoteDailyReportProperties, remoteMonthlyReportProperties, deviceRepository, proposalRepository);
        }

        @Bean
        @Autowired
        public FtpsManagerService ftpsManagerService(FTPSClient ftpsClient, MailService mailService, FtpsProperties ftpsProperties) {
            return new FtpsManagerService(ftpsClient, ftpsProperties, mailService);
        }

        @Bean
        public FTPSClient ftpsClient() {
            return new FTPSClient();
        }

        @Bean
        @Autowired
        public MailService mailService(MailProperties mailProperties, JavaMailSender javaMailSender, PgpProperties pgpProperties) {
            return new MailManagerService(mailProperties, javaMailSender, pgpProperties);
        }

        @Bean
        public JavaMailSender javaMailSender() {
            return new JavaMailSenderImpl();
        }

        @Bean
        @Autowired
        public RemoteReportMailService remoteReportMailService(RemoteReportMailProperties remoteReportMailProperties,
                                                               JavaMailSender javaMailSender,
                                                               Session session,
                                                               PgpProperties pgpProperties) {
            return new RemoteReportMailManagerService(remoteReportMailProperties, javaMailSender, session, pgpProperties);
        }

        @Bean
        @Autowired
        public Session getJavaMailReceiver(RemoteReportMailProperties remoteReportMailProperties) {
            Properties properties = new Properties();
            properties.put("mail.imap.host", remoteReportMailProperties.getImapHost());
            properties.put("mail.imap.port", remoteReportMailProperties.getImapPort());
            properties.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            properties.setProperty("mail.imap.socketFactory.fallback", "false");
            properties.setProperty("mail.imap.socketFactory.port", remoteReportMailProperties.getImapPort().toString());
            properties.put("mail.imap.debug", "true");
            properties.put("mail.imap.ssl.trust", "*");
            return Session.getDefaultInstance(properties);
        }
    }
...
}

那么,我的问题是如何在spring boot maven multimodule project中正确地为单元测试配置spring上下文,而不需要编写大量的配置代码?我也将感谢详细描述如何处理maven多模块项目的文章的链接。

共有1个答案

左丘昊天
2023-03-14

在阅读了各种文章和帖子后(如。在单元测试中使用SpringRunner可以吗?我意识到在运行测试时不需要整个应用程序上下文,相反,如果测试甚至不涉及和加载spring应用程序上下文(这样更快),我应该使用普通的@mock注释模拟bean依赖关系。但是,如果我需要一些应用程序上下文(例如,自动加载测试属性或仅用于集成测试),那么我使用为此准备的Spring Boot注释:@webmvctest@jpatest@springboottest等等。

例子:

普通模拟测试(不涉及spring):

public class UserServiceImplTest {

    @Mock
    private UserRepository userRepository;

    private UserServiceImpl userService;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        userService = new UserServiceImpl(userRepository);
    }

    /* Some tests here */

}
@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@EnableConfigurationProperties(value = DecisionProposalProperties.class)
@SpringBootTest(classes = {
        DecisionProposalRepositoryService.class,
        DecisionProposalMapperImpl.class
})
public class DecisionProposalRepositoryServiceTest {

    @MockBean
    private DecisionProposalRepository decisionProposalRepository;

    @MockBean
    private CommentRepository commentRepository;

    @Autowired
    private DecisionProposalRepositoryService decisionProposalRepositoryService;

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

    /* Some tests here */

}
@RunWith(SpringRunner.class)
@DataJpaTest
public class ImageProposalRepositoryTest {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private ImageProposalRepository imageProposalRepository;

    @Test
    public void testFindOne() throws Exception {
        ImageProposal imageProposal = ImageProposal.builder()
                .size(1024)
                .filePath("/test/file/path").build();
        entityManager.persist(imageProposal);
        ImageProposal foundImageProposal = imageProposalRepository.findOne(imageProposal.getId());
        assertThat(foundImageProposal).isEqualTo(imageProposal);
    }
}
 类似资料:
  • 我正在尝试为一个现有的应用程序编写单元测试用例,该应用程序有多个模块,每个模块中都有主类。有多个类具有\@SpringBootApplication。我写了一个简单的测试用例,它失败了,错误如下。我如何继续我的测试用例中的一个。 java.lang.IllegalStateException:在文件[C:\My Data\Workspace\Services2\MicroServices\Repo

  • 本章讨论使用 JUnit,Mockito,MRUnit 和 HBaseTestingUtility 对 HBase 应用程序进行单元测试。大部分信息来自关于测试 HBase 应用程序的社区博客文章。有关 HBase 本身的单元测试的信息,请参阅 hbase.tests 。 175. JUnit HBase 使用 JUnit 进行单元测试 此示例将单元测试添加到以下示例类: public class

  • 我有一个类似这样的项目结构: -应用 --模块 2 //库模块 --模块3 //库模块 我正在为我的多模块Android项目编写仪器测试用例,其中包含jaco代码覆盖范围。如果我从“app”模块执行检测测试用例,则仅为“app”模块类生成代码覆盖率。 因此,为了获得“模块2”的代码覆盖率 当我在非应用程序模块中执行插装测试用例,无法启动主活动,插装期间应用程序未启动,测试用例失败时,会出现问题。

  • 我有一个多模块maven项目,包含三个模块、和 Core具有以下依赖项定义 我已经为所有三个模块添加了Java9定义,的如下所示: 但是,我不知道如何让的测试类能够在测试执行期间看到类。当尝试测试运行时,找不到类。 如果向的添加需要My.Project.TestUtils;的: 然后在编译时,我得到一个错误,即找不到模块(大概是因为它只是作为测试依赖项引入的)。 在Java9模块化的世界中,如何处

  • 在单元测试中启动和正常关闭Spring应用程序的推荐方法是什么?我知道JUnit5的SpringExtension,但它在测试方法执行之前/之后启动和停止Spring上下文。 我想用测试方法启动和停止spring上下文,因为我想验证是否调用了某些方法(尤其是在关机期间)。 有没有推荐的方法来实现这一点?

  • 我有一个maven多模块项目。 所有测试都在称为tests/的单个模块中,所有代码都在单独的模块中。 有没有办法让我得到代码覆盖率?