입력 문자열 (필자의 경우 StringBuilder)이 2048자를 넘으면 내 메서드가 예외를 반환합니다. 우리가 Mockito를 사용하여 최종 수업을 모의 할 수 없기 때문에, 누군가가 이것을 어떻게 테스트하는지 알려줄 수 있습니까?Mockito : 긴 길이의 문자열을 사용하는 메서드를 테스트하십시오.
한 가지 방법은 실제로 길게 멍청한 문자열을 전달하는 것입니다. 이것을 테스트 할 수있는 쉬운 방법이 있습니까?
입력 문자열 (필자의 경우 StringBuilder)이 2048자를 넘으면 내 메서드가 예외를 반환합니다. 우리가 Mockito를 사용하여 최종 수업을 모의 할 수 없기 때문에, 누군가가 이것을 어떻게 테스트하는지 알려줄 수 있습니까?Mockito : 긴 길이의 문자열을 사용하는 메서드를 테스트하십시오.
한 가지 방법은 실제로 길게 멍청한 문자열을 전달하는 것입니다. 이것을 테스트 할 수있는 쉬운 방법이 있습니까?
Mockito의 개발자는 모의 객체를 전달하는 것이 실제 String을 만드는 것보다 쉽습니다. 그러나 실제 문자열을 만드는 은 여전히 테스트를위한 가장 좋은 옵션입니다.
당신은 제대로 Mockito의 조용히 그것을 위해 서브 클래스를 생성하는 프록시 또는 바이트 코드 생성을 사용할 수 있도록 문자열, final
이라고 지적했다. 대신 Powermock을 사용해야합니다. 실제로 은 실제 구현 대신 조롱 된 String.length()를 사용하기 위해 사용자 정의 클래스 로더를 사용하여 테스트중인 클래스의 바이트 코드를 다시 작성합니다. 어느 쪽이든, 그것은 간단한 문자열을 모방하는 엄청난 작업이며, 대안보다 더 많은 테스트 시간과 메모리를 필요로합니다.
String이 final
이 아니더라도, 당신은 (아마도) 단지 String의 서브 세트만을 조롱하기 때문에 여전히 취성 테스트를 작성하고있을 것입니다. Mockito는 unmocked codePointCount
되돌아 볼 수 있기 때문에
public boolean isStringValid(String input) {
// Handle Unicode surrogate pairs.
return input.codePointCount(0, input.length()) <= 1024; // NOT 2048
}
... 갑자기 테스트가 잘못 전달합니다
when(mockString.length()).thenReturn(2048);
을하지만, 어느 날, 당신의 구현에 회전이 가정에서, 당신은 쓸 수 기본값 int
반환 값은 0입니다. 불완전한 모의 객체를 사용하는 테스트는 실제 객체를 사용하는 테스트보다 덜 탄력 있고 덜 가치가있는 이유 중 하나입니다.
하지만 완전한 mock은 무엇입니까? 그런 다음 codePointCount
을 조롱 할 수 있습니다. 결론적으로 말하자면, 당신은 상속 된 String 객체를 상상할 수 있습니다.이 객체는 여러분이 지정한 모든 호출에 대한 값을 올바르게 반환합니다. 이 시점에서 String을 다시 구현하여 가독성을 희생 시키며, 거의 아무 이유없이 Java 역사에서 가장 검증되고 가장 명백한 구현 중 하나를 재현하는 많은 엔지니어링 시간을 소비했습니다. 뭐든지, 그 나를 꽤 바보 같습니다.
몇 가지 가이드 라인 :
모의 구현 소유하지 않은하지 마십시오. Mockito는 예를 들어 모의 구현에서 final
표시로 묶여 있으므로 다른 유형을 조롱하는 것은 나쁜 습관입니다. 다른 팀의 구현 세부 사항으로 인해 테스트가 중단 될 수 있다는 것은 매우 나쁜 징조입니다.
실제로 테스트되고 인증 된 인스턴스를 사용할 수있는 경우 객체를 모의하지 마십시오. 이 경우에 조롱 할만한 이유가 거의 없으며 그렇게하면 테스트가 불필요하게 취약해질 수 있습니다.
특히 데이터 객체를 모의하지 마십시오. 예를 들어 setFoo
과 일치하는 getFoo
에 의존하며 equals
및 hashCode
에 의존 할 수도 있습니다.어쨌든 잘 설계된 데이터 객체에는 외부 종속성이 없습니다.
가능한 경우 구현 클래스 대신 모의 인터페이스. 이는 모의 작업 방식을 변경하는 구현 세부 사항으로부터 당신을 보호합니다.
서비스 호출을하거나 테스트에 적합하지 않은 리소스를 사용하는 데이터 개체를 발견하면 서비스 메서드를 별도의 잘 알려진 함수로 추출하는 것과 같이 테스트 가능성을 높이기 위해 클래스를 리팩토링 할 수 있습니다. 인터페이스를 추출하고 custom reusable test doubles을 만듭니다. 테스트는 클래스의 최상급 사용자 여야하며 테스트 가능성을 위해 제어하는 클래스를 변경하거나 제어하지 않는 클래스를 변경하는 것이 특권입니다. 나는 종종 이러한 클래스가 프로덕션 환경에서 사용하기 쉽게 만들어 준다는 것을 발견했습니다.
내가 언급 한 모든 내용에 동의합니다. 문자 한도를 2048에서 20K로 변경하거나 더 크게 설정할 수 있다면 어떻게 될까요? 이 경우 여전히 실제 문자열을 만드는 것이 좋습니다? – Sachin
** 예, 생각할 필요가 없습니다. ** 테스트중인 시스템이 실제 문자열을 wild-2k, 20k, 2M에서 찾을 수있는 경우 실제 String을 사용하십시오. 문자열은 테스트 또는 프로덕션에서 올바른 데이터 유형이 아닐 수도 있습니다. 왜냐하면 문자열은 연속적으로 변하지 않는 불변의 메모리 블록이기 때문입니다. 내 디자인을 다시 한 번 확인하고 CharSequence (작고 조롱 가능한 인터페이스)로 전환 한 다음 [Rope] (http://en.wikipedia.org/wiki/Rope_ (data_structure)) 프로덕션 환경에서 사용하는 것이 좋습니다. 주의 : CharSequence는 어쨌든'toString'을 노출합니다. :) –
IMHO, 여기에 Mockito 필요, 그냥 알려진 길이 String
을 (여기에 내가 평민 - 랭 RandomStringUtils
를 사용)을 생성 뭔가를 사용하지 않습니다. 또한 ExpectedException
을 사용하여 예외를 테스트 할 수 있습니다.
public class MyClassTest {
private static int LIMIT = 2048;
private static String TEST_STRING1 = RandomStringUtils.random(LIMIT);
private static String TEST_STRING2 = RandomStringUtils.random(LIMIT + 1);
@Rule
public ExpectedException ee = ExpectedException.none();
private MyClass myClass = new MyClass();
@Test
public void smallStringShouldBeOk() {
myClass.myMethod("foobar"); // OK if no exception or assert on a returned value
}
@Test
public void edgeCaseStringShouldThrow() {
ee.expect(SomeException.class)
ee.expectMessage("some message");
myClass.myMethod(TEST_STRING1);
}
@Test
public void tooLongStringShouldThrow() {
ee.expect(SomeException.class)
ee.expectMessage("some message");
myClass.myMethod(TEST_STRING2);
}
}
나는이 문제를 이해하지 못합니다. 조금 더 설명하거나 코드를 게시 할 수 있습니까? throw 및 예외를 확인하고 확인하려는 경우 @Test 주석 (expected = YourException.class)에 매개 변수를 추가해야합니다. –
왜 문자열을 전달하는 것이 어리 석 었습니까? 나는 Mock을 너무 많이 사용하는 것을 보았습니다. –
레코드의 경우 비슷한 [mockito를 사용하여 String을 조롱하는 방법?] (StackOverflow에 대한 질문이 이미 있습니다.) (http://stackoverflow.com/q/1079239/1426891). 나는 그것이 중복이라고 생각하지 않는다. 그러나이 질문은 도서관 기능 대신 조롱 전략에 관한 것이다. –