Moq'ing 방법 어디서 표현>는 매개 변수로 전달됩니다.
나는 단위 테스트와 조롱을 처음 접했습니다! 데이터 저장소와 상호 작용하는 일부 코드를 다루는 단위 테스트를 작성하려고합니다. 데이터 액세스는 IRepository에 의해 캡슐화됩니다.
interface IRepository<T> {
....
IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate);
....
}
IRepository의 구체적인 IoC 구현을 활용하여 테스트하려는 코드는 다음과 같습니다.
public class SignupLogic {
private Repository<Company> repo = new Repository<Company>();
public void AddNewCompany(Company toAdd) {
Company existingCompany = this.repo.FindBy(c => c.Name == toAdd.Name).FirstOrDefault();
if(existingCompany != null) {
throw new ArgumentException("Company already exists");
}
repo.Add(Company);
repo.Save();
}
}
로직과 구체적인 리포지토리가 아닌 SignupLogic.AddNewCompany () 자체의 로직을 테스트하기 위해 IRepository를 조롱하고 SignupLogic에 전달합니다. 모의 저장소는 다음과 같습니다.
Mock<Repository> repoMock = new Mock<Repository>();
repoMock.Setup(moq => moq.FindBy(c => c.Name == "Company Inc")....
이름이 "Company Inc"로 설정된 Company 개체를 포함하는 메모리 내 IEnumberable을 반환합니다. SignupLogic.AddNewCompany를 호출하는 단위 테스트는 중복 된 세부 정보가있는 회사를 설정하고이를 전달하려고 시도하며 "Company already exists"라는 메시지와 함께 ArgumentException이 발생한다고 주장합니다. 이 테스트는 통과하지 못했습니다.
단위 테스트 및 AddNewCompany ()를 통해 디버깅을 실행하면 existingCompany가 항상 null 인 것처럼 보입니다. 절망적으로 FindBy 호출이 다음과 같이 보이도록 SignupLogic.AddNewCompany ()를 업데이트하면 발견했습니다.
Company existingCompany = this.repo.FindBy(c => c.Name == "Company Inc").FirstOrDefault();
테스트는 MOQ가 아니라 코드에 응답하는지 나에게 제안하는 통과 정확히 내 시험 설비에 설치를했습니다 같은. 중복 회사가 SignupLogic.AddNewCompany에 의해 거부되었는지 테스트하는 데는 분명히 유용하지 않습니다.
"Is.ItAny"를 사용하도록 moq.FindBy (...) 설정을 시도했지만 테스트도 통과하지 못합니다.
내가 읽고있는 모든 것에서, 내가하려는 것처럼 Expressions를 테스트하는 것은 실제로 여기에서 Moq로 할 수없는 것처럼 보일 것입니다. 가능합니까? 도와주세요!
Expression정확히 동일한 구조 (및 리터럴 값)를 가진 만 이 일치 하는 것이 맞을 것입니다 . Returns()mock이 호출되는 매개 변수를 사용할 수 있도록 오버로드를 사용하는 것이 좋습니다 .
repoMock.Setup(moq => moq.FindBy(It.IsAny<Expression<Func<Company, bool>>>())
.Returns((Expression<Func<Company, bool>> predicate) => ...);
에서는를 ...사용 predicate하여 일치하는 회사를 반환 할 수 있습니다 (일치하는 회사가 예상과 다른 경우 예외를 throw 할 수도 있음). 그다지 예쁘지는 않지만 작동 할 것이라고 생각합니다.
당신은 당신이하고자하는 It.IsAny<>()것을 성취 하기 위해 사용할 수 있어야합니다 . 를 사용하면 It.IsAny<>()설정의 반환 유형을 조정하여 코드의 각 분기를 테스트 할 수 있습니다.
It.IsAny<Expression<Func<Company, bool>>>()
첫 번째 테스트에서는 예외가 발생하도록하는 술어에 관계없이 회사를 반환합니다.
var repoMock = new Mock<IRepository<Company>>();
repoMock.Setup(moq => moq.FindBy(It.IsAny<Expression<Func<Company, bool>>>())).Returns(new List<Company>{new Company{Name = "Company Inc"}});
var signupLogic = new SignupLogic(repoMock.Object);
signupLogic.AddNewCompany(new Company {Name = "Company Inc"});
//Assert the exception was thrown.
두 번째 테스트, 반환 유형을 빈 목록 마녀로 만들면 add가 호출됩니다. :
var repoMock = new Mock<IRepository<Company>>();
repoMock.Setup(moq => moq.FindBy(It.IsAny<Expression<Func<Company, bool>>>())).Returns(new List<Company>());
var signupLogic = new SignupLogic(repoMock.Object);
signupLogic.AddNewCompany(new Company {Name = "Company Inc"});
repoMock.Verify(r => r.Add(It.IsAny<Company>()), Times.Once());
일반적으로 소유 한 유형 만 조롱합니다. 당신이 소유하지 않은 사람들은 다양한 어려움 때문에 실제로 조롱해서는 안됩니다. 따라서 질문의 이름에서 알 수 있듯이 조롱하는 표현은 갈 길이 아닙니다.
In Moq framework. It is important to put .Returns() for functions otherwise it is not matched. So if you have not done that, it is your problem.
repoMock.Setup(moq => moq.FindBy(c => c.Name == "Company Inc").Returns(....
'IT TIP' 카테고리의 다른 글
| Greasemonkey 네임 스페이스는 무엇에 필요합니까? (0) | 2020.12.08 |
|---|---|
| NoInitialContextException 오류의 의미 (0) | 2020.12.08 |
| pip를 사용하여 사용 가능한 Python 패키지를 검색하려면 어떻게해야합니까? (0) | 2020.12.08 |
| : hover에 반대되는 CSS 의사 클래스가 있습니까? (0) | 2020.12.08 |
| Angular 5의 헤더에 CORS 요청을 추가하는 방법 (0) | 2020.12.08 |