springboot Service層單元測試


兩個實現類實現同一個Service接口

public interface CustomUrlService {
    List<ShopMetrics> getShopMetrics();
}

@Service
public class CustomUrlServiceImpl implements CustomUrlService {
    @Override
    public List<ShopMetrics> getShopMetrics() {
        return null;
    }
}


@Service
public class CustomUrlServiceImpl2 implements CustomUrlService {
    @Override
    public List<ShopMetrics> getShopMetrics() {
        return Arrays.asList(new ShopMetrics(34L, 34L));
    }
}

使用的時候如果使用接口作為類型,直接使用@Autowired是無法找到具體是哪個bean的,因為@Autowired默認是按照類型注入的,需要加上@Qualifier注解指定實現類的bean id,如果@Service中沒有指定bean id(bean name),默認是類名的首字母小寫作為bean name。當然也可以使用@Resource注解,它默認是by name 注入的,所以變量名需要和待注入的實現類的bean name保持一致,如下所示:

    @Autowired
    @Qualifier("customUrlServiceImpl")
    private CustomUrlService customUrlServiceImpl;

    @Resource
    private CustomUrlService customUrlServiceImpl2;

@TestConfiguration

我之前在springboot中寫單元測試喜歡全部按照下面這種來寫測試類

@RunWith(SpringRunner.class)
@SpringBootTest
public class CustomUrlServiceImplTest {}

但是@SpringBootTest是把整個spring容器啟動起來,然后把測試環境給你准備好,這樣也是可以的,但是有時候只是顯得有點有點笨重,看日志就知道整個應用不管和這個單元測試有關沒關的都被啟動了,而我們只是為了跑一個單元單元測試。
看了參考資料1之后,我才知道了單元測試不一定需要啟動整個應用,層與層之間也可以並且應該隔離測試。如果上層測試需要用到下層的依賴,就使用mock的方式構造一個依賴。比如測試DAO層可以使用@DataJpaTest注解;測試controller層可以使用@WebMvcTest;測試Service層可以使用@TestConfiguration把需要用到Bean依賴進來。下面是測試Service層的一個例子:

@RunWith(SpringRunner.class)
public class CustomUrlServiceImplTest {
    @TestConfiguration
    static class prepareCustomServices{
        @Bean
        public CustomUrlService getCustomUrlServiceImpl() {
            return new CustomUrlServiceImpl();
        }

        @Bean
        public CustomUrlService getCustomUrlServiceImpl2() {
            return new CustomUrlServiceImpl2();
        }
    }

    @Autowired
    @Qualifier("getCustomUrlServiceImpl")
    private CustomUrlService customUrlServiceImpl;
    
    @Resource
    private CustomUrlService getCustomUrlServiceImpl2;
    
    @Test
    public void getShopMetrics() {
        assertNull(customUrlServiceImpl.getShopMetrics());
        assertNotNull(getCustomUrlServiceImpl2.getShopMetrics());
    }
}

現在再運行@Test標注的單元測試就不會啟動整個springboot容器中了。這里面需要注意的是使用 @Bean放入到spring容器的的bean的默認id是方法的方法名而不再是類名。

參考資料

  1. https://www.baeldung.com/spring-boot-testing
  2. https://dzone.com/articles/unit-and-integration-tests-in-spring-boot-2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM