스프링 테스트는 사실 쉬워요.

8356 단어 Spring테스트
과거의 직장 생활에서 나는 몇몇 사람들이 테스트 코드를 쓰지 않는 것을 자주 발견했는데, 그들이 쓰지 않는 이유는 여러 개의 다른 모듈을 덮어쓰는 테스트 용례를 쉽게 쓸 수 없기 때문이라고 주장했다.좋아, 나는 그들 중 대부분이 비교적 쉽게 파악할 수 있는 기술 수단이 부족하거나 그것을 명확하게 할 시간이 없다고 믿는다. 왜냐하면 업무 중에는 항상 진도와 같은 각종 스트레스가 있기 때문이다.어떻게 테스트해야 할지 모르기 때문에 통합 테스트를 소홀히 하는 경우가 많다. 이로 인해 발생하는 문제는 갈수록 나빠지는 소프트웨어, 점점 더 많은 버그와 실망하는 고객이다.그래서 저는 개인적인 경험을 공유하고 통합 테스트의 신비한 베일을 벗기고 싶습니다. 
Spring 기반 프로젝트에 대한 통합 테스트 향상 방법
사용 도구: Spring, JUnit, Mockito
일부 은행의 웹 서비스와 같은 외부 서비스를 통합한 스프링 프로젝트가 있다고 상상해 보세요.그러면 이 프로젝트를 위한 테스트 용례와 지속적인 통합 시스템에서 이러한 테스트를 완성할 때 겪는 문제는 기본적으로 많지 않다.
 1.매번 테스트는 거래가 진행되고 매번 거래는 금전적인 원가를 지불해야 하며 이런 원가는 최종적으로 고객이 부담한다.
 2.테스트 시 과도한 요청은 악의적인 요청으로 여겨질 수 있고 은행의 계좌가 봉쇄될 수 있으며 결과는 테스트 실패이다.
 3.비생산 환경을 사용하여 테스트를 진행할 때 테스트 결과는 결코 믿을 만하지 않으며 마찬가지로 결과는 테스트 실패이다.
일반적인 상황에서 단일 클래스를 테스트할 때 문제는 쉽게 해결된다. 왜냐하면 외부 서비스를 가상해서 호출할 수 있기 때문이다.그러나 전체 거대한 업무 프로세스를 테스트할 때 여러 개의 부품을 테스트해야 한다는 것을 의미한다. 이때 이 부품들을 스프링 용기에 포함시켜 관리해야 한다.다행히도 스프링은 매우 우수한 테스트 프레임워크를 포함하여 생산 환경 프로필에서 나온 bean을 테스트 환경에 주입할 수 있지만, 호출된 외부 서비스에 대해서는 우리가 직접 시뮬레이션을 작성해야 한다.일반인의 첫 반응은 테스트의 setUp 단계에서 스프링이 주입한 bean을 다시 주입(수정)하는 것일 수 있지만 이런 방법은 좀 더 꼼꼼히 고려해야 한다. 
경고: 이런 방식을 통해 당신의 테스트 코드는 용기 자체의 행위를 깨뜨렸기 때문에 실제 환경에서도 당신의 테스트 결과와 같다고 보장할 수 없습니다.
사실상, 우리는 먼저 시뮬레이션 클래스를 실현한 후에 그것을 필요한 bean에 다시 주입할 필요가 없다. 우리는 스프링이 우리가 처음부터 시뮬레이션 클래스를 주입하는 것을 도울 수 있다.우리 코드로 시범을 보여 봅시다.
예시 프로젝트는 Bank Service라는 클래스를 포함하고 호출된 외부 서비스를 대표하며, User Balance Service라는 클래스는 Bank Service를 호출합니다.UserBalance Service는 String에서 Double 형식으로 잔액을 전환하는 것만 간단하게 실현합니다.
BankService.java 소스:

 public interface BankService {
 String getBalanceByEmail(String email);
} 
BankServiceImpl.java 소스:

 public class BankServiceImpl implements BankService {
 @Override
 public String getBalanceByEmail(String email) {
  throw new UnsupportedOperationException("Operation failed due to external exception");
 }
} 
UserBalanceService.java 소스:

 interface UserBalanceService {
 Double getAccountBalance(String email);
} 
UserBalanceServiceImpl.java 소스:

 public class UserBalanceServiceImpl implements UserBalanceService {
 @Autowired
 private BankService bankService;
 @Override
 public Double getAccountBalance(String email) {
  return Double.valueOf(bankService.getBalanceByEmail(email));
 }
} 
그리고 Spring의 XML 프로필로 필요한 bean 설명을 추가합니다.
applicationContext.xml 소스 코드:

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">
 <bean id="bankService" class="ua.eshepelyuk.blog.springtest.springockito.BankServiceImpl"/>
 <bean id="userBalanceService" class="ua.eshepelyuk.blog.springtest.springockito.UserBalanceServiceImpl"/>
</beans> 
다음은 테스트 클래스 UserBalanceServiceImplTest입니다.java의 소스 코드:

 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/springtest/springockito/applicationContext.xml")
public class UserBalanceServiceImplProfileTest {
 @Autowired
 private UserBalanceService userBalanceService;
 @Autowired
 private BankService bankService;
 @Test
 public void shouldReturnMockedBalance() {
  Double balance = userBalanceService.getAccountBalance("[email protected]");
  assertEquals(balance, Double.valueOf(123.45D));
 }
} 
예상한 대로 테스트 방법은 Unsupported OperationException 이상을 보고합니다.우리의 현재 목적은 Bank Service를 우리의 시뮬레이션으로 바꾸는 것이다.모키토를 직접 사용해factory bean을 만드는 방법은 문제없지만 더 좋은 선택이 있습니다. Springockito 프레임워크를 사용하세요.계속하기 전에 대충 알아볼 수 있어요. 
남은 문제는 간단하다. 스프링을 실제 bean이 아닌 아날로그 bean에 주입하는 방법은 스프링 3.1 버전 이전에 XML 프로필을 새로 만드는 것 외에 다른 방법이 없다.그러나 Spring이 bean의 프로필 정의를 도입한 후에 우리는 더욱 우아한 해결 방식을 가지게 되었다. 비록 이런 방식도 테스트를 위한 XML 프로필이 추가로 필요하지만.다음은 테스트에 사용할 프로필testApplicationContext입니다.xml 코드:

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:mockito="http://www.mockito.org/spring/mockito"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.mockito.org/spring/mockito https://bitbucket.org/kubek2k/springockito/raw/tip/springockito/src/main/resources/spring/mockito.xsd">
 <import resource="classpath:/springtest/springockito/applicationContext.xml"/>
 <beans profile="springTest">
  <mockito:mock id="bankService" class="ua.eshepelyuk.blog.springtest.springockito.BankService"/>
 </beans>
</beans> 
수정된 테스트 클래스 UserBalanceServiceImplProfile Test.java의 소스 코드:

 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/springtest/springockito/testApplicationContext.xml")
@ActiveProfiles(profiles = {"springTest"})
public class UserBalanceServiceImplProfileTest {
 @Autowired
 private UserBalanceService userBalanceService;
 @Autowired
 private BankService bankService;
 @Before
 public void setUp() throws Exception {
  Mockito.when(bankService.getBalanceByEmail("[email protected]")).thenReturn(String.valueOf(123.45D));
 }
 @Test
 public void shouldReturnMockedBalance() {
  Double balance = userBalanceService.getAccountBalance("[email protected]");
  assertEquals(balance, Double.valueOf(123.45D));
 }
} 
setUp 방법에서 시뮬레이션 동작을 정의하고 클래스에 @Profile의 주석을 추가한 것을 알 수 있습니다.이 주석은springTest라는 프로필을 활성화하기 때문에Springockito 시뮬레이션된 bean을 사용하면 필요한 곳에 자동으로 주입할 수 있습니다.이 테스트의 실행 결과는 성공할 것입니다. 왜냐하면 스프링은 응용 프로그램 컨텍스트가 아닌 Springockito가 시뮬레이션한 버전을 주입했기 때문입니다.xml에서 설명한 버전입니다.
계속해서 테스트 최적화
만약 우리가 이 문제를 해결하는 방법을 한 걸음 더 추진할 수 있다면, 이 글은 비로소 결함이 없어 보인다.Springockito는 또 다른 이름을 제공했습니다.
Springockito Annotation의 프레임워크입니다. 테스트 클래스에서 주석을 사용하여 아날로그 클래스를 주입할 수 있습니다.계속 보기 전에, 당신은 먼저 사이트에 가서 대충 보는 것이 가장 좋습니다.자, 다음은 수정된 테스트 코드입니다.

 UserBalanceServiceImplAnnotationTest.java :
 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = SpringockitoContextLoader.class,
 locations = "classpath:/springtest/springockito/applicationContext.xml")
public class UserBalanceServiceImplAnnotationTest {
 @Autowired
 private UserBalanceService userBalanceService;
 @Autowired
 @ReplaceWithMock
 private BankService bankService;
 @Before
 public void setUp() throws Exception {
  Mockito.when(bankService.getBalanceByEmail("[email protected]")).thenReturn(String.valueOf(valueOf(123.45D)));
 }
 @Test
 public void shouldReturnMockedBalance() {
  Double balance = userBalanceService.getAccountBalance("[email protected]");
  assertEquals(balance, valueOf(123.45D));
 }
} 
여기에 새로 도입된 XML 프로필이 아니라 정식 환경의 응용 프로그램Context를 직접 사용하고 있음을 주의하십시오.xml.우리는 @Replace WithMock이라는 주석을 사용하여 Bank Service 형식의 bean을 표시한 다음 setUp 방법에서 아날로그 클래스의 행동을 정의했습니다.
후기
Springockito-annotations 프로젝트는 우리의 테스트 코드를 덮어쓰기에 의존하는 기초 위에 세우는 큰 장점이 있다. 이를 통해 우리는 추가 XML 프로필을 정의할 필요도 없고 테스트를 위해 생산 환경의 프로필을 변경할 필요도 없다.Springockito-annotations를 사용하지 않는다면, 우리는 추가 XML 프로필을 정의하는 것 외에 다른 선택이 없습니다.따라서 통합 테스트에서 Springockito-annotations를 사용하면 테스트 용례가 생산 코드에 미치는 영향을 최대한 줄이고 추가 XML 프로필을 유지하는 부담을 없앨 수 있습니다.
덧붙이다
스프링 프로젝트를 위한 통합 테스트를 쓰는 것은 정말 간단하군요. 글의 코드는 참고하십시오나의 GitHub
번역문 링크:http://www.codeceo.com/article/spring-test-is-easy.html
Test Me If You Can #1(Spring Framework)
농망 C 샌드박스 왕
이상은 본문의 전체 내용입니다. 여러분의 학습에 도움이 되고 저희를 많이 응원해 주십시오.

좋은 웹페이지 즐겨찾기