2013-11-26 2 views
2

EasyMock (3.2)을 사용하고 있습니다. Spring Security를 ​​기반으로하는 보안 시스템의 일부에 대한 테스트를 작성하려고합니다. 나는 Authentication을 모의 해 빈 권한리스트를 리턴하도록하고 싶다. 와일드 카드로 제네릭 메서드의 동작을 모의 사용하는 방법

Collection<? extends GrantedAuthority> getAuthorities(); 

그래서 내가 테스트 쓰기 : 다음과 같이 그 메소드 선언은

Authentication authentication = createMock(Authentication.class); 
Collection<? extends GrantedAuthority> authorities = Collections.emptyList(); 
expect(authentication.getAuthorities()).andReturn(authorities); 

을하지만 컴파일러는 andReturn 전화에 세 번째 줄에 대해 불평 :

The method andReturn(Collection<capture#1-of ? extends GrantedAuthority>) in the type IExpectationSetters<Collection<capture#1-of ? extends GrantedAuthority>> is not applicable for the arguments (Collection<capture#2-of ? extends GrantedAuthority>

무엇 내가 틀렸어?


UPDATE :

나는 authorities의 선언 변경하는 경우 :

제안
Collection<GrantedAuthority> authorities = Collections.emptyList(); 

, 여전히 컴파일되지 않습니다,하지만 오류가 조금 다릅니다

The method andReturn(Collection<capture#1-of ? extends GrantedAuthority>) in the type IExpectationSetters<Collection<capture#1-of ? extends GrantedAuthority>> is not applicable for the arguments (Collection<GrantedAuthority>)

나는 GrantedAuthority은 두 선언에서 모두 동일합니다 (org.springframework.security.core.GrantedAuthority).

+1

와일드 카드 일반이 필요합니까, 아니면 그냥'Collection '로 갈 수 있습니까? – GriffeyDog

+0

getAuthorities() getter의 실제 반환 유형은 무엇입니까? – Joe

+0

반환 형식의 메서드에서 상한의 와일드 카드를 사용하는 것은 대개 잘못된 생각입니다. 메소드가 무한 일반 타입을 반환하도록하십시오. – Seelenvirtuose

답변

5

컬렉션 선언에서 항목 유형을 제거하면 경고 메시지가 표시되지만 테스트가 작동합니다.그래서 두 방법 모두 기본적으로 같은 일을하지만 expect(T value)IExpectationSetters가 될하는

public static <T> IExpectationSetters<T> expect(final T value) { 
    return getControlForLastCall(); 
} 

public static <T> IExpectationSetters<T> expectLastCall() { 
    return getControlForLastCall(); 
} 

@SuppressWarnings("unchecked") 
private static <T> IExpectationSetters<T> getControlForLastCall() { 
    // snip 
    return (IExpectationSetters<T>) lastControl; 
} 

:

authentication.getAuthorities(); 
expectLastCall().andReturn(authorities); 

이의이 두 가지 방법을 살펴 보자 :

@Test 
public void testFoo() 
    { 
    // setup 
    Authentication mockAuthentication = createMock(Authentication.class); 
    Collection authorities = Collections.emptyList(); 
    expect(mockAuthentication.getAuthorities()).andReturn(authorities); 

    // exercise 
    EasyMock.replay(mockAuthentication); 
    Collection<? extends GrantedAuthority> retAuth = mockAuthentication.getAuthorities(); 

    // verify 
    EasyMock.verify(mockAuthentication); 
    assertEquals(authorities, retAuth); 
    } 
0

Collection<? extends GrantedAuthority>은 을 확장하는 일부 알려지지 않은 클래스 을 의미합니다. 따라서 두 개의 별개의 선언 인 Collection<? extends GrantedAuthority>은 와일드 카드와 관련하여 두 가지 다른 클래스가 될 수 있습니다. 그것이 컴파일러가 불평하는 이유입니다.

당신은 물론 GrantedAuthority 또는 그 서브 클래스의 모든 인스턴스를 허용 할 GrantedAuthorityCollection이 컬렉션에 추가 할 의미 Collection<GrantedAuthority>을 할 수 있습니다.

+0

질문에 대한 내 업데이트를 참조하십시오. – fracz

+0

'authentication.getAuthorities())'도'Collection '를 반환하도록 선언되어야합니다. – GriffeyDog

0

이 특정 문제에 대한 해결책은 Authentication 인터페이스 대신 AbstractAuthenticationToken 클래스를 조롱하는 것입니다. 봄부터 기본 구현은 getPrincipals() 메서드를 재정의하고 반환 된 형식을 Collection<? extends GrantedAuthority>에서 Collection<GrantedAuthority>으로 변경합니다. 작업 코드 :

AbstractAuthenticationToken authentication = createMock(AbstractAuthenticationToken.class); 
Collection<GrantedAuthority> authorities = Collections.emptyList(); 
expect(authentication.getAuthorities()).andReturn(authorities); 

그러나 이것은 일반적으로 문제를 해결하지 못합니다.

2

조롱 프레임 워크를 사용하여이 기능을 테스트 할 수있는 쉬운 방법은 없습니다. 타입 캐스팅에 의지해야 할 수도 있습니다. 와일드 카드의 경우 제네릭이 가장 많이 사용됩니다. 즉, 최상위 수준에서만 와일드 카드를 지정할 수 있습니다. 따라서 EasyMock 또는 임의의 조롱 프레임 워크는 와일드 카드가 포함 된 무언가의 모의 객체를 효과적으로 만들 수 없습니다. 당신이 메시지를 보면 :

IExpectationSetters<Collection<? extends GrantedAuthority>> 

두 가지 수준의 깊이와 컴파일러를 포기 이유입니다.

0

가장 쉬운 대신 expectLastCall()에 의지하는 것입니다 value과 동일한 유형 인 반면 expectLastCall()은 원하는 모든 것을 반환합니다.

관련 문제