Reputation: 54532
I use Moq to mock the GetCollection
method but the line crashes.
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);
This is the error I got
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()
Any idea about hot to fix it?
Upvotes: 3
Views: 3347
Reputation: 151664
The accepted answer doesn't work for C# driver version 1.9.1 and uses some undisclosed types introduced by OP. I have altered the helper methods that allow for mocking a 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;
}
}
Usage:
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;
Upvotes: 5
Reputation: 54532
After reading the source code, I figured out I missed some properties or methods to mock.
Here is the working code:
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;
}
Upvotes: 3