2014-12-02 3 views
1

.NET 4.5, EF6에서 작업 중이며 JustMock 2.0을 사용하여 테스트 중입니다. 응용 프로그램JustMock - 다른 클래스의 동일한 메소드 결과를 반환하여 모든 인스턴스에 대한 메소드 모의 방법 (공용 인터페이스 공유)

내가 조롱에 의해 내 데이터베이스를 조롱하려고 내 DbContext 서브 클래스 :.. CoreDataRepositoryContext

을 위해, 나는 회원에게 SaveChanges를의 DbContext 모든 DbSet을 조롱 할 필요가 가짜 데이터 컬렉션을 반환하여 내 클래스 CoreDataRepositoryContext의 입력 된 속성.

  • 내가 의 모든 인스턴스 CoreDataRepositoryContextDbSet을 조롱 할 필요가
  • AsQueryable

를 제거

  • 추가 : 나는 또한 다음 DbSet의 회원을 조롱 할 필요가

    예를 들어, 나는 en 유형 이다 DbSet < 주문> 및 FakeOrders

    // FakeOrders is a list of orders (List<Order>) 
    
    var mockedContext = Mock.Create<CoreDataRepositoryContext>(); 
    
        // Mock works 
    Mock.Arrange(() => mockedContext.SaveChanges()).IgnoreInstance().DoNothing(); 
        // Mock works 
    Mock.Arrange(() => mockedContext.Orders).IgnoreInstance().ReturnsCollection(FakeOrders); 
        // Mock works 
    Mock.Arrange(() => mockedContext.Orders.Add(Arg.IsAny<Order>())).IgnoreInstance().DoInstead((Order o) => FakeOrders.Add(o)); 
        // Mock works 
    Mock.Arrange(() => mockedContext.Orders.Remove(Arg.IsAny<Order>())).IgnoreInstance().DoInstead((Order o) => FakeOrders.Remove(o)); 
        // Mock DOES NOT work ! 
    Mock.Arrange(() => mockedContext.Orders.AsQueryable()).IgnoreInstance().Returns(() => FakeOrders.AsQueryable()); 
    

    mockedContext.Orders : 데이터베이스에 입력 주문의 tities (표 주문) 이 나는 ​​테이블을 주문을 조롱하기 위해 다음과 같은했다 유형이 이고 목록이 <입니다.입니다. 두 클래스 모두 IEnumerable < 순서> 인터페이스를 구현합니다. 두 가지 방법 중 어느 것도 인터페이스 IEnumerable을 < T>에 선언되어 있기 때문에 구성원을 제거 추가 도발

    는 잘 작동합니다. 한편

    , AsQueryable이 인터페이스 선언 Queryable에서 의해 정의된다. 내가 는 IEnumerable < T>를 구현하는 모든 클래스의 인스턴스에서 AsQueryable를 호출 IgnoreInstance를 사용하여 회원을 조롱 그래서, 끝없는 루프를 시작합니다. 를 IEnumerable < 주문> .AsQueryable이 FakeOrders.AsQueryable
    에 의해 조롱 때문에 내가 할 수있는 방법 ... FakeOrders.AsQueryable ... 무한 루프에 의해

    var query = mockedContext.Orders.AsQueryable(); // Infinite loop 
    query = FakeOrders.AsQueryable(); // Infinite loop 
    query = new List<Order>().AsQueryable(); // Infinite loop 
    

    을 조롱하는 모의 제품 만 DbSet <>.AsQueryable 구체적으로 조롱하지 않고 IEnumerable < 주문> .AsQueryable을 사용합니다. IgnoreInstance?

    당신의 도움이 :) 당신은 단지 마지막 배열에서 IgnoreInstance()을 제거 할 수 있습니다

  • 답변

    0

    생성자가 GetMockContext()으로 대체되어 조롱 된 컨텍스트를 다시 실행합니다.

    private static CoreDataRepositoryContext GetMockContext() 
    { 
         CoreDataRepositoryContext mockContext = new CoreDataRepositoryContext(); 
    
         Mock.Arrange(() => mockContext.SaveChanges()).DoNothing(); 
    
         Mock.Arrange(() => mockContext.Set<Order>()).ReturnsCollection(FakeOrders); 
         Mock.Arrange(() => mockContext.Orders).ReturnsCollection(FakeOrders); 
         Mock.Arrange(() => mockContext.Orders.Add(Arg.IsAny<Order>())).DoInstead((Order o) => FakeOrders.Add(o)); 
         Mock.Arrange(() => mockContext.Orders.Remove(Arg.IsAny<Order>())).DoInstead((Order o) => FakeOrders.Remove(o)); 
         Mock.Arrange(() => mockContext.Orders.Find(Arg.IsAny<object[]>())).Returns((object[] param) => FakeOrders.Find(x => x.Id == (Guid)param[0])); 
         Mock.Arrange(() => mockContext.Orders.AsQueryable()).Returns(() => FakeOrders.AsQueryable()); 
    
         // Then arrange all DbSets... 
    
         return mockContext; 
    } 
    
    public static FakeDataList<Order> FakeOrders = new List<Order>(); 
    
    +0

    [JustMock.EntityFramework] (http://www.nuget.org/packages/JustMock.EntityFramework/)로 많은 일을 할 수 있습니다. –

    0

    주셔서 감사합니다. 이렇게하면 Orders 속성에서 호출 될 때만 작동합니다.

    기술적으로는 이러한 메서드를 Orders 속성에 배치 할 필요는 없습니다. ReturnsCollection은 대상에 모든 IList<T> 및 모든 IQueryable<T> 메서드를 프록시 처리합니다 (대상에서 해당 인터페이스를 구현하는 경우). FakeOrders이 목록이므로 및 Remove (Orders)은 백업 컬렉션의 동일한 방법으로 프록시됩니다. AsQueryable은 인스턴스 메소드가 아니며 확장 메소드입니다. 따라서 파생 된 특정 유형에 대해 조롱 할 수는 없지만 그렇게 할 필요는 없습니다. AsQueryable의 원래 구현은 충분히 유연하므로 모방하지 않아도됩니다.

    마지막 세 가지 조치 만 제거하면 테스트가 예상대로 작동합니다.

    내가 IgnoreInstance와 DbContext을 마련하지 않지만 인수로 특정 연결 문자열로 전화했을 때 내 DbContext 서브 클래스의 생성자를 정렬 :

    string myConnectionString = "CoreDBTestConnection"; 
    
    // Arrange all CoreDataRepositoryContext instances for this connection string 
    Mock.Arrange(() => new CoreDataRepositoryContext(myConnectionString).Returns(GetMockContext()); 
    

    드디어 해결 방법을 발견했다 좋아

    +0

    Stephan, – Valone

    +0

    Stefan에게 도움을 주셔서 감사합니다. 사실 내 응용 프로그램의 비즈니스 계층 논리에 따라'IgnoreInstance'를 사용해야합니다. 사실 나는 새로운 _Repository_를 생성하기 위해 _Managers_를 테스트하고 데이터베이스에 액세스 할 필요가있을 때마다 새로운'CoreDataRepositoryContext'를 테스트하려고합니다. 그래서, 모든 테스트를 커버하기 위해 내 테스트 클래스의 _ClassInitialize_ 메소드에있는 인스턴스와 관계없이'CoreDataRepositoryContext'를 정렬합니다. 메쏘드를 정렬하지 않고 단지'Orders' 속성 만 정렬하려고했지만 작동하지 않고 그 메쏘드가 호출 될 때 데이터베이스가 요구됩니다. – Valone

    관련 문제