Effort - FirstOrDefault는 Faking Database 일 때 null을 반환합니다.

c# effort entity-framework mocking unit-testing

문제

내 프로젝트에 대한 단위 테스트를 만들려고 노력하고있다. 주위를 파고 들다가 아이디어가 훌륭하다. DBContext를 위조하는 대신 데이터베이스를 조롱한다. 복잡한 스키마를 사용합니다.

그러나 내가 특별히 전자 메일 데이터베이스에 추가 한 후 사용자의 전자 메일을 가져 오려고 노력 중입니다. 노력으로 작성합니다. 코드는 다음과 같습니다.

MyContext contextx = new MyContext(Effort.DbConnectionFactory.CreateTransient());

var client = new Client
{
    ClientId = 2,
    PersonId = 3,
    Person = new Person
    {
        PersonId = 3,
        EMail = "xxxxx@gmail.com"
    }
};
contextx.Client.Add(client); //<-- client got added, I checked it and is there

var email = contextx.Client.Select(c => c.Person.EMail).FirstOrDefault(); 

위의 마지막 줄에서는 xxxx@gmail.com이라는 전자 메일을 반환 할 수 없으며 항상 null을 반환합니다.

어떤 아이디어?

수락 된 답변

직접적인 질문에 대답하기

질문하신 특정 질문에 대해서는 다음 두 가지를 제안합니다.

  1. contextx.Client.ToArray() 를보고 해당 컬렉션에 실제로 얼마나 많은 멤버가 있는지 확인하십시오. Client 컬렉션이 실제로 비어있을 수 있습니다.이 경우 실제로 null이됩니다. 또는 Client 컬렉션의 첫 번째 요소에 EMail 대한 null 값이있을 수 있습니다.

  2. contextx.SaveChanges() 에서 Client 컬렉션을 쿼리하기 전에 contextx.SaveChanges() 를 호출하면 어떻게 동작이 변경됩니까? SaveChanges 를 호출하면 새로 삽입 된 값이 컬렉션에 존재하게되는지 궁금합니다. 이것은 꼭 필요한 것은 아니지만 Effort와 DbContext 사이에 이상한 상호 작용이있을 수 있습니다.

편집 : SaveChanges() 대답 밝혀졌습니다.

일반 테스트 제안

"unit-testing"태그를 사용하여이 질문에 탭을 지정 했으므로, 필자는 10 년 동안 실무자 및 코치로서의 유닛 테스팅을 토대로 몇 가지 일반적인 단위 테스트 조언을 제공 할 것입니다. 단위 테스트는 응용 프로그램의 여러 작은 부분을 개별적으로 테스트하는 것입니다. 일반적으로 이는 단위 테스트가 한 번에 몇 개의 클래스와 만 상호 작용한다는 것을 의미합니다. 이것은 또한 단위 테스트가 외부 라이브러리 또는 종속성 (예 : 데이터베이스)에 의존하지 않아야 함을 의미합니다. 반대로 통합 테스트는 시스템의 더 많은 부분을 동시에 수행하며 데이터베이스와 같은 것에 대한 외부 종속성을 가질 수 있습니다.

이 용어는 전문 용어를 둘러싼 말처럼 들릴 수도 있지만 테스트의 실제 의도를 다른 팀 구성원에게 전달할 때이 용어가 중요합니다.

이 경우 DbContext에 의존하는 일부 기능을 단위 테스트하거나 데이터 액세스 계층을 테스트하려고합니다. 직접 DbContext에 의존하는 무언가에 대한 분리 된 단위 테스트를 작성하려는 경우 DbContext에 대한 종속성을 깨야합니다. 아래에서 DbContext에 대한 종속성 깨기 에서 설명 할 것입니다. 그렇지 않으면 엔티티 매핑 방법을 포함하여 DbContext를 통합 테스트하려고합니다. 이 경우 필자는 항상 이러한 테스트를 격리하고 실제 (로컬) 데이터베이스를 사용하는 것이 가장 좋습니다. 프로덕션 환경에서 사용하는 것과 동일한 종류의 로컬에 설치된 데이터베이스를 사용하려고합니다. 종종 SqlExpress는 잘 작동합니다. 테스트가 데이터베이스의 인스턴스에서 이루어지면 테스트가 완전히 휴지통으로 바뀔 수 있습니다. 각 테스트를 실행하기 전에 기존 데이터를 제거하십시오. 그런 다음 기존 데이터가 충돌 할 염려없이 필요한 데이터를 설정할 수 있습니다.

DbContext에 대한 의존성 깨기

그렇다면 비즈니스 로직이 DbContext 에 액세스 할 때 좋은 단위 테스트를 작성하는 방법은 무엇입니까? 너는하지 않는다.

데이터 지속성을 위해 Entity Framework를 사용하는 응용 프로그램에서 DbContext 에 대한 액세스가 별도의 데이터 액세스 프로젝트에 포함되어 있는지 확인합니다. 일반적으로 리포지토리 패턴을 구현하는 클래스를 만들고 이러한 클래스는 DbContext 종속되도록 허용됩니다. 그래서이 경우 IClientRepository 인터페이스를 구현하는 ClientRepository 를 만들 것입니다. 인터페이스는 다음과 같습니다.

public interface IClientRepository {

    Client GetClientByEMail(string email);

}

그런 다음 메서드에 액세스해야하는 클래스는 기본 스텁 / 모의 / 기타를 사용하여 단위 테스트를 수행 할 수 있습니다. DbContext 를 조롱하는 것에 대해 걱정할 필요는 없습니다. 데이터 액세스 계층이 포함되어 있으므로 실제 데이터베이스를 사용하여 철저하게 테스트 할 수 있습니다. 데이터 액세스 계층을 테스트하는 방법에 대한 제안은 위의 내용을 참조하십시오.

이 인터페이스의 구현은 하나의 통일 된 장소에서 이메일 주소로 Client 를 찾는 것이 무엇을 의미 하는지를 정의합니다. IClientRepository 인터페이스를 사용하면 "우리 시스템에서 Client 엔터티를 어떻게 쿼리합니까?"라는 질문에 신속하게 대답 할 수 있습니다.

DbContext 에 종속성을 DbContext 것은 도메인 클래스가 연결 문자열에 종속성을 가지게하고 모든 곳에서 ADO.Net 코드를 사용하도록 허용하는 것과 거의 동일한 테스트 문제의 규모입니다. 즉, 실제 데이터가 포함 된 실제 데이터 저장소 (가짜 데이터베이스 포함)를 생성해야합니다. 그러나 특정 데이터 액세스 어셈블리 내의 DbContext 대한 액세스가 포함되어 있으면 단위 테스트를 훨씬 쉽게 작성할 수 있습니다.

프로젝트 구성에 관한 한, 일반적으로 데이터 액세스 프로젝트 만 Entity Framework에 대한 참조를 허용합니다. 엔티티를 정의하는 별도의 핵심 프로젝트가 있습니다. 핵심 프로젝트에서 데이터 액세스 인터페이스를 정의 할 것입니다. 그런 다음 구체적인 인터페이스 구현이 데이터 액세스 프로젝트에 적용됩니다. 솔루션의 대부분의 프로젝트는 핵심 프로젝트에 대한 종속성을 취할 수 있으며 최상위 실행 파일 또는 웹 프로젝트 만 데이터 액세스 프로젝트에 의존해야합니다.




아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.