IT박스

단위 테스트를 위해 C #에서 파일 시스템을 어떻게 모방합니까?

itboxs 2020. 6. 23. 07:57
반응형

단위 테스트를 위해 C #에서 파일 시스템을 어떻게 모방합니까?


단위 테스트를 작성하기 위해 C #에서 파일 시스템을 모방하는 라이브러리 또는 메소드가 있습니까? 현재의 경우 특정 파일이 있는지 확인하고 생성 날짜를 읽는 방법이 있습니다. 앞으로는 그 이상이 필요할 수 있습니다.


편집 : NuGet 패키지를 설치하십시오 System.IO.Abstractions.

이 답변이 처음 수락되었을 때이 패키지는 존재하지 않았습니다. 아래의 역사적 맥락에 대한 원래 답변이 제공됩니다.

인터페이스를 만들어서 할 수 있습니다.

interface IFileSystem {
    bool FileExists(string fileName);
    DateTime GetCreationDate(string fileName);
}

System.IO.File.Exists () 등을 사용하는 '실제'구현을 작성합니다. 그런 다음 조롱 프레임 워크를 사용하여이 인터페이스를 조롱 할 수 있습니다. Moq을 추천 합니다.

편집 : 누군가가 이것을하고 친절하게 온라인으로 여기에 게시했습니다 .

이 방법을 사용하여 IClock 인터페이스 (시간 흐름을 제어 할 수있는 테스트에 실제로 유용합니다!)에서 DateTime.UtcNow를 조롱하고보다 전통적으로 ISqlDataAccess 인터페이스를 사용했습니다.

또 다른 방법은 TypeMock 을 사용하는 것입니다 . 이렇게하면 클래스 호출을 가로 채고 스텁 할 수 있습니다. 그러나 이것은 비용이 들며, 실행하기 위해서는 전체 팀의 PC와 빌드 서버에 설치해야 할 것입니다. 또한 mscorlib를 스텁수 없으므로 System.IO.File에서는 작동하지 않을 것입니다 .

또한 특정 방법을 단위로 테스트 할 수 없다는 점을 받아들이고 느리게 실행되는 별도의 통합 / 시스템 테스트 스위트에서 테스트 할 수 있습니다.


설치 패키지 시스템 IO 요약

가상 라이브러리에 대한 NuGet 패키지가 현재 존재 System.IO.Abstractions System.IO 네임 스페이스를 멀리 추상화.

또한 작성시에는 부분적으로 만 구현되지만 매우 좋은 출발점이되는 일련의 테스트 도우미 System.IO.Abstractions.TestingHelpers가 있습니다.


파일 시스템에서 필요한 것을 정의한 다음 해당 기능에 대한 래퍼를 작성하는 계약을 작성해야 할 것입니다. 그 시점에서 구현을 조롱하거나 스텁 아웃 할 수 있습니다.

예:

interface IFileWrapper { bool Exists(String filePath); }

class FileWrapper: IFileWrapper
{
    bool Exists(String filePath) { return File.Exists(filePath); }        
}

class FileWrapperStub: IFileWrapper
{
    bool Exists(String filePath) 
    { return (filePath == @"C:\myfilerocks.txt"); }
}

시스템 네임 스페이스에서 주로 사용되는 유형에 대한 래퍼를 제공 하므로 http://systemwrapper.codeplex.com/ 을 사용하는 것이 좋습니다.


나는 이것에 대한 다음과 같은 솔루션을 보았습니다.

  • 단위 테스트가 아닌 통합 테스트를 작성하십시오. 이것이 작동하려면 다른 테스트 방해에 대해 걱정하지 않고 물건을 덤프 할 수있는 폴더를 만드는 간단한 방법이 필요합니다. 사용할 테스트 메서드 폴더마다 고유 한 간단한 TestFolder 클래스가 있습니다.
  • 모의 가능한 System.IO.File을 작성하십시오. 그것이 IFile.cs 입니다. 이것을 사용하면 종종 모의 진술을 작성할 수 있음을 증명하는 테스트로 끝나지만 IO 사용량이 적을 때 사용합니다.
  • 추상화 계층을 검사하고 클래스에서 파일 IO를 추출하십시오. 이를위한 인터페이스를 만듭니다. 나머지는 통합 테스트를 사용하지만 매우 작습니다. ioThingie.loadSettings ()와 같이 의도를 작성하십시오.
  • System.IO.Abstractions . 나는 이것을 아직 사용하지는 않았지만, 내가 가지고 놀기에 가장 흥분되는 것입니다.

내가 쓰고있는 것에 따라 위의 모든 방법을 사용하게됩니다. 그러나 대부분 IO에 닿는 단위 테스트를 작성할 때 추상화가 잘못되었다고 생각합니다.


.NET 파일 API는 실제로 조롱 될 수있는 인터페이스 나 확장 가능한 클래스를 기반으로하지 않기 때문에 테스트에서 파일 시스템을 조롱하기가 어렵습니다.

그러나 파일 시스템에 액세스하기위한 자체 기능 계층이있는 경우 단위 테스트에서이를 모방 할 수 있습니다.

조롱에 대한 대안으로 테스트 설정의 일부로 필요한 폴더와 파일을 생성하고 분해 방법에서 삭제하는 것을 고려하십시오.


파일 시스템을 어떻게 조롱할지 잘 모르겠습니다. 당신이 할 수있는 일은 테스트에 필요한 구조로 폴더 등을 만드는 테스트 픽스처 설정을 작성하는 것입니다. 테스트가 실행 된 후 분해 방법으로 정리할 수 있습니다.

추가 편집 : 이것에 대해 조금 더 생각할 때,이 유형의 메소드를 테스트하기 위해 파일 시스템을 모방하고 싶지는 않습니다. 파일 시스템을 모의하여 특정 파일이 존재하는 경우 true를 반환하고 해당 파일이 존재하는지 확인하는 방법을 테스트 할 때 파일 시스템을 사용하면 아무 것도 테스트하지 않습니다. 파일 시스템을 조롱하는 것은 파일 시스템에 종속 된 메소드를 테스트하려고하지만 파일 시스템 활동이 테스트중인 메소드의 필수 요소가 아닌 경우에 유용합니다.


특정 질문에 대답하려면 : 아니오, 파일 I / O 호출 (내가 아는)을 조롱 할 수있는 라이브러리가 없습니다. 즉, 유형을 "적절하게"단위 테스트하려면 유형을 정의 할 때이 제한 사항을 고려해야합니다.

"적절한"단위 테스트를 정의하는 방법에 대한 간단한 참고 사항. 단위 테스트를 통해 알려진 입력을 제공 한 예상 출력 (예외, 메소드 호출 등)을 얻을 수 있는지 확인해야한다고 생각합니다. 이를 통해 단위 테스트 조건을 일련의 입력 및 / 또는 입력 상태로 설정할 수 있습니다. 내가 찾은 가장 좋은 방법은 인터페이스 기반 서비스 및 종속성 주입을 사용하여 유형 외부의 각 책임이 생성자 또는 속성을 통해 전달 된 인터페이스를 통해 제공되도록하는 것입니다.

So, with this in mind, back to your question. I've mocked file system calls by creating a IFileSystemService interface along with a FileSystemService implementation that is simply a facade over the mscorlib file system methods. My code then uses the IFileSystemService rather than the mscorlib types. This allows me to plug in my standard FileSystemService when the application is running or mock the IFileSystemService in my unit tests. The application code is same regardless of how it's run, but the underlying infrastructure allows that code to be easily tested.

I'll acknowledge that it's a pain to use the wrapper around the mscorlib file system objects but, in these specific scenarios, it's worth the extra work as the testing becomes so much easier and more reliable.


Creating an interface and mocking it for testing is the cleanest way to go. However, as an alternative yo could take a look at the Microsoft Moles framework.


You can do that using Microsoft Fakes without the need to change your codebase for example because it was frozen already.

First generate a fake assembly for System.dll - or any other package and then mock expected returns as in:

using Microsoft.QualityTools.Testing.Fakes;
...
using (ShimsContext.Create())
{
     System.IO.Fakes.ShimFile.ExistsString = (p) => true;
     System.IO.Fakes.ShimFile.ReadAllTextString = (p) => "your file content";

      //Your methods to test
}

By using System.IO.Abstractions and System.IO.Abstractions.TestingHelpers like that:

public class ManageFile {
   private readonly IFileSystem _fileSystem;
   public ManageFile(IFileSystem fileSystem){

      _fileSystem = fileSystem;
   }

   public bool FileExists(string filePath){}
       if(_fileSystem.File.Exists(filePath){
          return true;
       }
       return false;
   }
}

In your Test Class, you use MockFileSystem() to mock file and you instanciate ManageFile like:

var mockFileSysteme = new MockFileSystem();
var mockFileData = new MockFileData("File content");
mockFileSysteme.AddFile(mockFilePath, mockFileData );
var manageFile = new ManageFile(mockFileSysteme);

Common solution is using some abstract filesystem API (like Apache Commons VFS for Java ): all application logic uses API and unit test is able to mock real filesystem with stub implementation (in-memory emulation or something like that).

For C# the similar API exists: NI.Vfs which is very similar to Apache VFS V1. It contains default implementations both for local filesystem and in-memory filesystem (last one can be used in unit tests from the box).


We currently use a proprietary data engine and its API is not exposed as interfaces so we can hardly unit test our data access code. Then I went with Matt and Joseph's approach too.


나는 Jamie Ide의 응답으로 갈 것입니다. 쓰지 않은 것을 조롱하려고하지 마십시오. 봉인 클래스, 비가 상 메소드 등 알지 못하는 모든 종속성이 있습니다.

또 다른 방법은 적절한 방법으로 적절한 방법을 래핑하는 것입니다. 예를 들어 File 메소드에 액세스 할 수 있지만 모방 할 수있는 FileWrapper라는 클래스를 작성하십시오.

참고 URL : https://stackoverflow.com/questions/1087351/how-do-you-mock-out-the-file-system-in-c-sharp-for-unit-testing

반응형