귀하의 질문은 개발자가 테스트에 들어가기 가장 어려운 테스트 중 하나를 노출시킵니다.
"도대체 내가 무엇을 테스트해야합니까?"
예제는 API 호출을 서로 붙이기 때문에 매우 흥미롭지 않으므로 단위 테스트를 작성하려면 메서드가 호출되었다는 단언이됩니다. 이와 같은 테스트는 구현 세부 사항을 테스트에 밀접하게 연결합니다. 구현 세부 사항을 변경하면 테스트가 중단되므로 메소드의 구현 세부 사항을 변경할 때마다 테스트를 변경해야하기 때문에 이것은 나쁩니다!
나쁜 테스트를하는 것은 실제로 테스트를하지 않는 것보다 더 나쁩니다.
귀하의 예에서 :
void DoIt(IZipper zipper, IFileSystem fileSystem, IDllRunner runner)
{
string path = zipper.Unzip(theZipFile);
IFakeFile file = fileSystem.Open(path);
runner.Run(file);
}
모의를 전달할 수는 있지만 테스트 방법에는 논리가 없습니다. 이를 위해 단위 테스트를 시도하면 다음과 같이 보일 수 있습니다.
// Assuming that zipper, fileSystem, and runner are mocks
void testDoIt()
{
// mock behavior of the mock objects
when(zipper.Unzip(any(File.class)).thenReturn("some path");
when(fileSystem.Open("some path")).thenReturn(mock(IFakeFile.class));
// run the test
someObject.DoIt(zipper, fileSystem, runner);
// verify things were called
verify(zipper).Unzip(any(File.class));
verify(fileSystem).Open("some path"));
verify(runner).Run(file);
}
축하합니다. 기본적으로 DoIt()
메소드 의 구현 세부 사항을 테스트에 복사하여 붙여 넣었습니다 . 행복한 유지.
테스트를 작성할 때 HOW가 아닌 WHAT 를 테스트하려고합니다 .
자세한 내용은 블랙 박스 테스트 를 참조하십시오 .
무엇 당신의 방법의 이름 (또는 적어도 그것은이어야 함). 는 어떻게 모든 방법 안에 살고있는 작은 구현 세부 사항입니다. 좋은 테스트를 통해 WHAT 를 중단하지 않고 HOW 를 교체 할 수 있습니다 .
이런 식으로 생각하고 스스로에게 물어보십시오.
"공개 계약을 변경하지 않고이 방법의 구현 세부 사항을 변경하면 테스트가 중단됩니까?"
대답이 예이면 WHAT가 아니라 HOW를 테스트하는 것 입니다.
파일 시스템 종속성을 사용하여 코드를 테스트하는 것에 대한 특정 질문에 대답하기 위해 파일에 대해 좀 더 흥미로운 내용이 있고 Base64로 인코딩 된 내용을 byte[]
파일 에 저장하려고한다고 가정 해 봅시다 . 이를 위해 스트림을 사용하여 코드의 작동 방식 을 확인하지 않고도 코드가 올바르게 작동하는지 테스트 할 수 있습니다. 한 가지 예는 다음과 같습니다 (Java).
interface StreamFactory {
OutputStream outStream();
InputStream inStream();
}
class Base64FileWriter {
public void write(byte[] contents, StreamFactory streamFactory) {
OutputStream outputStream = streamFactory.outStream();
outputStream.write(Base64.encodeBase64(contents));
}
}
@Test
public void save_shouldBase64EncodeContents() {
OutputStream outputStream = new ByteArrayOutputStream();
StreamFactory streamFactory = mock(StreamFactory.class);
when(streamFactory.outStream()).thenReturn(outputStream);
// Run the method under test
Base64FileWriter fileWriter = new Base64FileWriter();
fileWriter.write("Man".getBytes(), streamFactory);
// Assert we saved the base64 encoded contents
assertThat(outputStream.toString()).isEqualTo("TWFu");
}
테스트는 사용 ByteArrayOutputStream
되지만 응용 프로그램에 반환 (아마도 FileStreamFactory라고 함) 실제 StreamFactory (의존성 주입을 사용) FileOutputStream
에서 outputStream()
하고 쓸 것이다 File
.
이 write
방법에서 흥미로운 점은 Base64로 인코딩 된 내용을 작성하고 있다는 것입니다. 그래서 우리가 테스트 한 것입니다. 귀하의 경우 DoIt()
방법이 더 적절하게 테스트 할 것입니다 통합 테스트 .