2014-01-15 2 views
3

Moq를 사용하여 GetCollection 메서드를 조롱했지만 행이 충돌합니다.Mocking MongoCollection 충돌 - 호출 대상에 의해 예외가 throw되었습니다.

var collectionSettings = new MongoCollectionSettings 
{ 
    GuidRepresentation = GuidRepresentation.Standard, 
    ReadEncoding = new UTF8Encoding(), 
    ReadPreference = new ReadPreference(), 
    WriteConcern = new WriteConcern(), 
    WriteEncoding = new UTF8Encoding() 
}; 

var collection = new Mock<MongoCollection<BsonDocument>>(database.Object, "MyCollection", collectionSettings); 

//crashing here without any error dumped 
database.Setup(f => f.GetCollection("MyCollection", collectionSettings)).Returns(collection.Object); 

이것은 내가 그것을 해결하기 위해 뜨거운 대해 어떤 생각을

Exception of type 'System.ArgumentOutOfRangeException' was thrown. 
Parameter name: name 
    at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) 
    at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
    at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) 
    at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) 
    at System.Activator.CreateInstance(Type type, Object[] args) 
    at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance(Type proxyType, List`1 proxyArguments, Type classToProxy, Object[] constructorArguments) 
    at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors) 
    at Moq.Proxy.CastleProxyFactory.CreateProxy(Type mockType, ICallInterceptor interceptor, Type[] interfaces, Object[] arguments) 
    at Moq.Mock`1.<InitializeInstance>b__0() 
    at Moq.PexProtector.Invoke(Action action) 
    at Moq.Mock`1.InitializeInstance() 
    at Moq.Mock`1.OnGetObject() 
    at Moq.Mock.GetObject() 
    at Moq.Mock.get_Object() 
    at Moq.Mock`1.get_Object() 

있어 오류가 무엇입니까?

+1

당신이 시도/캐치를 사용하는 경우입니까? 일반적으로 이러한 종류의 실패는 일반적으로 'GetCollection'이 무시할 수 없음을 나타냅니다. – Tejs

+0

@Tejs 오 예. 고마워! 이것은 '{ "System.ArgumentOutOfRangeException 유형의 예외가 발생했습니다. 오류입니다. \ r \ n 매개 변수 이름 : name"}' – zsong

+1

실제 메서드 정의 인 GetCollection이 실행되고있는 것처럼 보입니다. 전화. 너의 모의가 충분하지 않다고 생각해. – Tejs

답변

2

소스 코드를 읽은 후, 나는 몇 가지 속성이나 모의 방법을 놓친 것을 알았습니다. 여기

는 작업 코드 :

public MongoServer GetMockedMongoDbServer() 
{ 
    var serverSettings = new MongoServerSettings 
    { 
     Servers = new List<MongoServerAddress> 
     { 
      new MongoServerAddress("unittest") 
     } 
    }; 
    var server = new MongoServer(serverSettings); 
    return server; 
} 

public static Mock<MongoCollection<T>> CreateMockCollection<T>(MongoDatabase database, string name) 
{ 
    var collectionSetting = new MongoCollectionSettings(); 
    var m = new Mock<MongoCollection<T>>(database, name, collectionSetting); 
    m.Setup(x => x.Database).Returns(database); 
    m.Setup(x => x.Settings).Returns(collectionSetting); 
    return m; 
} 

public MongoDatabase GetMockedMongoDb(MongoServer server) 
{ 
    var databaseSettings = new MongoDatabaseSettings() 
    { 
     GuidRepresentation = GuidRepresentation.Standard, 
     ReadEncoding = new UTF8Encoding(), 
     ReadPreference = new ReadPreference(), 
     WriteConcern = new WriteConcern(), 
     WriteEncoding = new UTF8Encoding() 
    }; 

    var database = new Mock<MongoDatabase>(server, "db_name", databaseSettings); 

    var message = String.Empty; 

    //need to mock the following stuff 
    database.Setup(db => db.Settings).Returns(databaseSettings); 
    database.Setup(db => db.IsCollectionNameValid(It.IsAny<string>(), out message)).Returns(true); 

    //mock the collection 
    var c = CreateMockCollection(database.Object, "MyCollectionName"); 
    database.Setup(f => f.GetCollection("MyCollectionName")).Returns(c.Object); 

    return database.Object; 
} 

public IMongoDbContext GetMockedMongoContext() 
{ 
    var server = GetMockedMongoDbServer(); 
    var database = GetMockedMongoDb(server); 

    var mongoDbContext = new Mock<IMongoDbContext>(); 
    mongoDbContext.Setup(x => x.GetMongoDatabase()).Returns(database); 

    return mongoDbContext.Object; 
} 
2

허용 된 대답은 C#을 드라이버 버전 1.9.1 작동하지 않습니다과 영업 이익에 의해 도입 된 몇 가지 공개되지 않은 유형을 사용합니다. 나는 MongoCollection<T>을 조롱 수 있도록 도우미 방법을 변경 한 :

public static class MongoMock 
{ 
    public static Mock<MongoServer> CreateMongoServer() 
    { 
     var serverSettings = new MongoServerSettings 
     { 
      Servers = new List<MongoServerAddress> 
      { 
       new MongoServerAddress("MockServer") 
      } 
     }; 

     var server = new Mock<MongoServer>(MockBehavior.Strict, serverSettings); 

     string message; 
     server.Setup(s => s.Settings).Returns(serverSettings); 
     server.Setup(s => s.IsDatabaseNameValid(It.IsAny<string>(), out message)).Returns(true); 

     return server; 
    } 

    public static Mock<MongoDatabase> CreateMongoDatabase(MongoServer server) 
    { 
     var databaseSettings = new MongoDatabaseSettings 
     { 
      GuidRepresentation = GuidRepresentation.Standard, 
      ReadEncoding = new UTF8Encoding(), 
      ReadPreference = new ReadPreference(), 
      WriteConcern = new WriteConcern(), 
      WriteEncoding = new UTF8Encoding() 
     }; 
     var database = new Mock<MongoDatabase>(MockBehavior.Strict, server, "MockDatabase", databaseSettings); 

     string message; 
     database.Setup(db => db.Server).Returns(server); 
     database.Setup(db => db.Settings).Returns(databaseSettings); 
     database.Setup(db => db.IsCollectionNameValid(It.IsAny<string>(), out message)).Returns(true); 

     return database; 
    } 

    public static Mock<MongoCollection<T>> CreateMongoCollection<T>(MongoDatabase database, string collectionName) 
    { 
     var collectionSetting = new MongoCollectionSettings(); 
     var collectionMock = new Mock<MongoCollection<T>>(MockBehavior.Strict, database, collectionName, collectionSetting); 
     collectionMock.Setup(x => x.Database).Returns(database); 
     collectionMock.Setup(x => x.Settings).Returns(collectionSetting); 
     return collectionMock; 
    } 

    public static Mock<MongoCollection<T>> CreateMongoCollection<T>(string collectionName) 
    { 
     var server = CreateMongoServer().Object; 
     var database = CreateMongoDatabase(server); 
     return CreateMongoCollection<T>(database.Object, collectionName); 
    } 

    public static Mock<MongoCursor<T>> CreateMongoCursor<T>(MongoCollection<T> collection, IEnumerable<T> items = null) 
    { 
     var cursorMock = new Mock<MongoCursor<T>>(MockBehavior.Strict, collection, null, null, null, null); 

     if (items != null) 
     { 
      cursorMock.Setup(c => c.GetEnumerator()).Returns(items.GetEnumerator()); 
     } 

     return cursorMock; 
    } 
} 

사용법 : 당신이 오류를 잡을 수

var serverMock = MongoMock.CreateMongoServer(); 
var server = serverMock.Object; 

var databaseMock = MongoMock.CreateMongoDatabase(serverMock.Object); 
var database = databaseMock.Object; 

var collectionMock = MongoMock.CreateMongoCollection<BsonDocument>(databaseMock.Object, "FooCollection"); 
var collection = collectionMock.Object; 

var cursorMock = MongoMock.CreateMongoCursor(collectionMock.Object, new List<BsonDocument>()); 
var cursor = cursorMock.Object; 
+0

모의 수집 데이터를 추가하는 방법은 무엇입니까? –

+0

@Usama'collectionMock'에'Find()'를 설정하여'MongoMock.CreateMongoCursor()'를 통해 생성)을 호출하면'IEnumerable '을 제공 할 수 있습니다.이 호출은' 찾기()'. – CodeCaster

+2

이 코드를이 요점과 완벽하게 공유 할 수 있습니까? –

관련 문제