파일 이름에 isFile (std.file에서)을 호출 한 다음 .1, .2, .3 등을 추가하여 각 파일이 있는지 여부를 확인하는 기능이 있습니다.표준 라이브러리 함수 모의 방법 D
단위 테스트를하고 싶지만 isFile을 조롱해야합니다.
나는 약간 둘러 보았고 클래스를 모의하는 방법을 찾았지만 하나의 기능은 찾지 못했습니다.
파일 이름에 isFile (std.file에서)을 호출 한 다음 .1, .2, .3 등을 추가하여 각 파일이 있는지 여부를 확인하는 기능이 있습니다.표준 라이브러리 함수 모의 방법 D
단위 테스트를하고 싶지만 isFile을 조롱해야합니다.
나는 약간 둘러 보았고 클래스를 모의하는 방법을 찾았지만 하나의 기능은 찾지 못했습니다.
내 대답이 Adam 's와 약간 다르므로 추가하고 추가 할 수 있습니다.
"범위가 지정된 가져 오기"를 사용할 수 있습니다. 문서 여기 http://dlang.org/module.html
에서 각각의 섹션을 참조하십시오 또한 작동 예를 들어, 당신은 유닛 테스트 블록 내부에 isFile
기능을 모의 할 수있는 방법 (그것이 "모의 객체"모듈에 정의되어 가정) 것
import std.file;
import std.stdio;
int main(string[] args)
{
writeln(isFile("qq.d"));
return 0;
}
unittest
{
import mocks;
writeln(isFile("qq.d"));
}
내 간단한 솔루션 다음, 별도의 모듈에 기능을 조롱 당신이 원하는 어느 하나를 선택할 수 version(unittest)
을 사용하는 것입니다
version(unittest)
import mocks.file;
else
import std.file
void main() { isFile("foo"); } // std.file normally, mocks.file in test mode
지역 수입 세르게이 노솝 어떤 경우에 작동하지만, 내가 르 상단 생각 이 경우
string test_me() { isFile("qq.d"); return "do something"; }
unittest {
assert(test_me() == "do something");
}
ISFILE가 너무 멀리 떨어져 시험에서 사용되기 때문에, 범위 지정된 가져 오기가 작동하지 않을 것입니다 : 일반적으로 당신이 당신의 자신의 기능을 테스트 할 것 때문에 VEL 하나 더있다. 그러나 사용 지점에서 가져 오는 version(unittest)
은 필요에 따라 함수를 재정의 할 수 있습니다.
아마도 최고의 조합이 될 것입니다 :
string test_me() {
version(unittest) bool isFile(string) { return true; }
else import std.file : isFile;
isFile("qq.d"); return "do something";
}
로컬 가짜 함수를 정의입니다 ...하지만 난 함수 아무튼 이후로 내가 그것을 생각 이니까, 그 중 하나 좋아하지 않아 반드시 테스트 방법을 알아야합니다. 어쩌면 수입 된 mocks
모듈은 실제로 함수 포인터 또는 unittest 블록에서 재 할당 할 수있는 것을 만듭니다 .... 음, 함수 콜렉션이 아닌 완전한 블로워 라이브러리 여야 할 수도 있습니다.
하지만 두 가지 대답 사이에는 잠재적 인 해결책이 있다고 생각합니다.
는, 좀 미친 짓이 어떤 링커의 트릭을 사용하여 다른 모듈의 기능을 대체 전역하는 것이 가능하다는 것을 비록 내가 언급 할 세 번째 일 :
import std.file;
import std.stdio;
// our replacement for isFile...
pragma(mangle, std.file.isFile.mangleof)
static bool isFile(string) { return true; }
int main(string[] args)
{
writeln(isFile("qq.d")); // always does true
return 0;
}
작동하는 이유 pragma (mangle)는 링커가 보는 이름을 변경합니다. 링커가 동일한 이름을 가진 두 개의 함수 (라이브러리와 사용자 코드)를 보면 사용자 코드가 개별 라이브러리 함수를 바꿀 수 있습니다.
따라서 lib 대신에 우리의 함수가 사용됩니다. 중요한 정보는 다음과 같습니다. 함수 시그니처가 일치해야합니다. 그렇지 않으면 함수 시그니처가 실행될 때 충돌이 발생하고 한 위치가 아닌 전체 프로그램에 대한 함수가 바뀝니다. 하지만 버전 (unittest)과 함께 사용할 수 있습니다.
실제로이 트릭을 사용하는 것은 좋지 않습니다. 실수로 실수를 범하면 무작위로 충돌하는 경향이 있으며, std lib 기능을 대체하려고 생각하면서 실수를 저지르는 경향이 있습니다.
아마도이 트릭 + 함수 포인터를 사용하여 런타임에 함수를 바꿀 수 있습니다. 그래도 중요한 문제는 링커가 라이브러리 함수를 함수로 완전히 대체했기 때문에 원래 구현을 전혀 사용할 수 없다는 것입니다.
또한 전체 std lib 모듈을 직접 작성하고 동일한 이름을 지정하고 컴파일러에 명시 적으로 전달하여 대체 할 수 있습니다. Phobos에서 개발 작업을 수행하는 중 때때로이를 수행합니다. 그러나 이것은 을 것으로 대체하고 컴파일러 명령 행의 차이점이므로 단위 테스트에도 유용하지 않을 수 있습니다.
그건 유용한 옵션입니다. 하나의 의견. 모듈을 로컬에서 가져 오는 것은 좋은 습관으로 보이며 어느 정도까지는 좋은 D 실습으로 광고됩니다. 따라서 test_me 함수는 모듈을 로컬로 가져올 수 있으며 두 번째 솔루션은 작동하지 않습니다. 그리고이 경우 테스터에 대해 사려 깊게 생각한다면 컴파일 타임 매개 변수 또는 무언가를 제공해야합니다. –
예, 그렇습니다. 현지 수입이 좋습니다. –
하나의 옵션은 버전 (단위 테스트) 또는 다른 것을 기반으로 가져 오기를 변경하는 것일 수 있습니다 ... 그래서 실제 아이디는 std.file.isFile을 사용하지만 unittest는 your.mocks.isFile을 사용합니다. –
아이디어를 주셔서 감사합니다. 이 도로를 따라 가면 사용 된 std 함수를 일부 객체로 래핑하고 실제 객체 또는 mock을 인스턴스화할지 여부를 결정하는 팩토리를 사용하는 것을 선호합니다. 나는 아직도 더 외과 적 해결책을 찾고있다 :) – garph0
죄송합니다, 다시 현지 수입에 문제가 있습니까? 마찬가지로 import std.file; import std.stdio; int main (string [] args) { writeln (isFile ("qq.d"))); return 0; } unittest { 수입품] writeln (isFile ("qq.d")); } –