문자열을 키로 사용하고 조롱 된 클래스 Candidate
의 인스턴스를 값으로 사용하는 Map을 만들고 싶습니다.JMockit이 두 개 이상의 클래스 인스턴스를 모의 수 없습니다.
Map<String, Long> domainNameToId = new HashMap<String, Long>();
domainNameToId.put("farmaciapuentezurita.es", 1234l);
domainNameToId.put("vivefarma.com", 2345l);
domainNameToId.put("eurofarmacia.com", 3456l);
Map<String, Candidate> expectedCandidates = new HashMap<String, Candidate>();
for(String domain : domainNameToId.keySet()) {
final Candidate cand = new MockUp<Candidate>() {
@Mock Long getDomainId() { return domainNameToId.get(domain); } // private method
@Mock boolean validateAndPrepare() { return true; }
@Mock String getRepresentingName() { return domain; }
}.getMockInstance();
expectedCandidates.put(domain, cand);
}
1.28에 1.20에서 JMockit를 업그레이드하기 전에 작동하는 데 사용되는 위의 코드.
java.lang.IllegalStateException :
는 지금은 예외 얻을에 무 모형 에서 클래스 com.urlservice.data.Candidate의 초기화되지 않은 인스턴스를 얻기 위해 잘못된 시도를 ...
내가 설명서를 읽고 다음과 같은 방식으로 대신 new MockUp(T targetInstance)
을 사용하려고 (이 루프의 몸) :
final Candidate cand = new Candidate(domain);
new MockUp<Candidate>(cand) {
@Mock Long getDomainId() { return domainNameToId.get(domain); } // private method
@Mock boolean validateAndPrepare() { return true; }
@Mock String getRepresentingName() { return domain; }
};
결과가 매우 이상합니다. 처음 후보자가 조롱을 당했고 나머지 조롱 된 후보자는 전혀 조롱을받지 않았고 실제 방법이 호출되었습니다.
java.lang.IllegalArgumentException가 : 이미 조롱 : 클래스 com.urlservice.data.Candidate 에서 아무 소용
final Candidate cand = new Candidate(domain); new Expectations(cand) {{ cand.getDomainId(); result = domainNameToId.get(domain); // Had to make it public :-( cand.validateAndPrepare(); result = true; cand.getRepresentingName(); result = domain; }};
:
나는 다시Expectations
API로 되돌리려 시도 ...
정말 최신 버전으로 업그레이드하고 싶지만이 문제의 해결 방법을 찾을 수 없습니다.
업데이트 : 최대 1.28 버전에서이 문제를 재현하지 못했습니다. 따라서이 버전이 출시 된 것 같습니다.
또한 제 2의 예 (new MockUp(T targetInstance)
)와 관련하여, 클래스 MockUp
라인 402의 소스 코드를 살펴보고 예상되는 동작이 첫 번째 인스턴스가 아닌 특정 타겟 인스턴스를 조롱하지 않는 것처럼 보입니다.
MockUp<?> previousMockUp = findPreviouslyFakedClassIfMockUpAlreadyApplied();
if (previousMockUp != null) {
targetType = previousMockUp.targetType;
mockedClass = previousMockUp.mockedClass;
return; // Input param targetInstance is disregarded
}
무엇이 누락 되었습니까?
UPDATE2 : 나는 실패한 테스트 예를 생각해 냈습니다. 조금 번거 롭긴하지만 포인트를 얻을 것이라고 확신합니다.
public class SampleTest {
class TestedClass {
private IncrementingDependency dep;
TestedClass(IncrementingDependency dep) { this.dep = dep; }
public int getVal() { return dep.inc(); }
}
class IncrementingDependency {
int val;
public IncrementingDependency(int val) { this.val = val; }
public int inc() { return ++val; }
}
@Test
public void sampleTest() {
List<Integer> inputVals = Arrays.asList(1, 2, 3);
List<TestedClass> incrementingClasses = new ArrayList<TestedClass>();
for (Integer num : inputVals) {
IncrementingDependency dep = new IncrementingDependency(num);
new MockUp<IncrementingDependency>(dep) {
@Mock int inc() { return num; } // Mock with different behavior - DON'T INCREMENT
};
incrementingClasses.add(new TestedClass(dep));
}
assertThat(incrementingClasses.get(0).getVal()).isEqualTo(1); // Passes - 1 wasn't incremented (mocked behavior)
assertThat(incrementingClasses.get(1).getVal()).isEqualTo(2); // Fails - real code was called and 2 was incremented to 3
assertThat(incrementingClasses.get(2).getVal()).isEqualTo(3); // We never get to this point
}
}
이 예제는 실패하지 않았을 경우에도, 내가
MockUp
의 생성자에 전달하기 전에 내 의존성을 인스턴스화 할 필요가 있다는 사실은 기껏해야 문제가 있다는 점 유의 하시길 바랍니다. 모의 객체를 만드는 전체적인 요점은 인스턴스화 할 필요가 없다는 것입니다.
private void expectCandidatesFromMap(final Map<String, Long> domainNameToId) {
Map<String, Candidate> expectedCandidates = new HashMap<String, Candidate>();
class MockedCandidate extends MockUp<Candidate> {
private final String domainName;
private final Long domainId;
MockedCandidate(String domainName) {
this.domainName = domainName;
this.domainId = domainNameToId.get(domainName);
}
@Mock Long getDomainId() { return domainId; }
@Mock String getRepresentingName() { return domainName; }
@Mock boolean validateAndPrepare() { return true; }
}
for (String domain : domainNameToId.keySet()) {
expectedCandidates.put(domain, new MockedCandidate(domain).getMockInstance());
}
}
내 테스트는 지금은 '돈에 합격하더라도 :
'새로운 MockUp (cand)'을 사용하면 "이상한"결과를 재현 할 수 없습니다. 그것은 1.28로 잘 작동하는 것 같습니다. 실패한 예제 테스트를 보여줄 수 있습니까? –
'Mock (T)'에 대한 [API 문서] (http://jmockit.org/api1x/mockit/MockUp.html#MockUp-T-)에는 "주어진 인스턴스에만 영향을 미친다"고되어 있습니다. 따라서,'Candidate'의 * 다른 * 인스턴스에서 호출 된 메소드는'@ Mock' 메소드로 넘어 가지 않습니다. –
@ Rogério 물론, 그게 내가 성취하려고했던 것입니다. 나는 실패한 예제 테스트를 최대한 빨리 제공하려고 노력할 것입니다. 그러나 JMockit 코드 샘플을 맨 끝에 넣으면 내 주장이 강력하게 뒷받침되지 않습니까? – KidCrippler