2017-01-15 5 views
0

테스트를 만들 때 첫 번째 MVC, 부트, 데이터 웹 앱을 만들고 문제가 있습니다. 나는 크레이그 월 (Craig Wall)의 책 "Spring in Action"에서 몇 가지 예를 수정했다. registerNewAccount 메서드에 대해 컨트롤러에 TDD 테스트를 쓰려고했지만, 모든 것이 정상이지만, 항상 argumetns are different!이되었습니다. 아래의 전체 스택 추적 :스프링 MVC 컨트롤러의 TDD 테스트가 올바르게 작동하지 않습니다.

Argument(s) are different! Wanted: 
accountService.create(
    [email protected] 
); 
-> at com.conf.controller.AccountControllerSpec.registerNewUser(AccountControllerSpec.java:52) 
Actual invocation has different arguments: 
accountService.create(
    [email protected] 
); 
-> at com.conf.controller.AccountController.registerNewAccount(AccountController.java:32) 

Argument(s) are different! Wanted: 
accountService.create(
    [email protected] 
); 
-> at com.conf.controller.AccountControllerSpec.registerNewUser(AccountControllerSpec.java:52) 
Actual invocation has different arguments: 
accountService.create(
    [email protected] 
); 
-> at com.conf.controller.AccountController.registerNewAccount(AccountController.java:32) 

    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 

내 컨트롤러 클래스 :

@Controller 
@RequestMapping(value = "/account") 
public class AccountController { 

    private AccountService accountService; 

    @Autowired 
    public AccountController(AccountService accountService){ 
     this.accountService = accountService; 
    } 

    @RequestMapping(value = "/register", method = RequestMethod.GET) 
    public String showRegistrationForm(){ 
     return "account/register"; 
    } 

    @RequestMapping(value = "/register", method = RequestMethod.POST) 
    public String registerNewAccount(Account account){ 
     accountService.create(account); 
     return "redirect:/"; 
    } 

} 

내 서비스 클래스 :

@Service 
@Transactional 
public class AccountService { 


    private AccountRepository repository; 

    @Autowired 
    public AccountService(AccountRepository repository) { 
     this.repository = repository; 
    } 

    public Account create(Account account){ 
     return repository.save(account); 
    } 
} 

내 저장소 클래스 :

@Component 
public interface AccountRepository extends CrudRepository<Account, Long>{ 

} 

그리고 내 사양 클래스 :

public class AccountControllerSpec { 

    private MockMvc mockMvc; 
    private AccountService service; 
    private AccountController controller; 

    @Before 
    public void before(){ 
     service = mock(AccountService.class); 
     controller = new AccountController(service); 
     mockMvc = standaloneSetup(controller).build(); 

    } 

    @Test 
    public void registrationPage() throws Exception { 
      mockMvc.perform(get("/account/register")).andExpect(view().name("account/register")); 
    } 

    @Test 
    public void registerNewAccount() throws Exception { 
     Account unsaved = new Account("M","B","[email protected]"); 
     Account saved = new Account("M","B","[email protected]"); 

     when(service.create(unsaved)).thenReturn(saved); 

      mockMvc.perform(post("/account/register") 
        .param("firstName","M") 
        .param("lastName","B") 
        .param("email","[email protected]")) 
        .andExpect(redirectedUrl("/")); 


     verify(service,atLeastOnce()).create(unsaved); 
    } 
} 

내가 뭘 잘못 했니?

답변

2

컨트롤러가 unsaved 계정으로 서비스를 요청할 것으로 예상됩니다. 그러나 컨트롤러를 호출하면 Spring은 요청에서 보낸 매개 변수로 새 Account 인스턴스를 만들고 해당 계정으로 서비스를 호출합니다 (unsaved과 같지 않음).

따라서 스프링에 의해 생성 된 실제 인스턴스가 unsaved과 같도록 모든 equals() 및 hashCode()를 정의하거나, Account를 허용하는 다른 매처를 사용하거나, ArgumentCaptor를 사용하여 전달 된 실제 계정을 캡처하십시오. 귀하의 서비스를 점검하고 예상되는 특성을 가지고 있는지 확인하십시오.

+0

다른 일치 자의 예를 들어 주시겠습니까? – Ice

+0

'(service.create (any))). then return (saved); ' –

+0

'any()'를 사용하면 좋은 생각이라고 말해 줄 수 있습니까? @JB Nizet – Ice