C# 单元测试MongoWrite异常
我想使用Mongo驱动程序测试我对MongoWriteException的处理,下面是一个示例方法:C# 单元测试MongoWrite异常,c#,mongodb,nunit,moq,mongodb-.net-driver,C#,Mongodb,Nunit,Moq,Mongodb .net Driver,我想使用Mongo驱动程序测试我对MongoWriteException的处理,下面是一个示例方法: private void Update() { try { var find = Builders<Filter>.Filter.Eq(e => e.Id, "someId"); var update = Builders<Filter>.Update.Set(e =&g
private void Update()
{
try
{
var find = Builders<Filter>.Filter.Eq(e => e.Id, "someId");
var update = Builders<Filter>.Update.Set(e => e.SomeValue, "AValue");
_documentStore.MongoCollection<Filter>().UpdateOne(find, update, new UpdateOptions { IsUpsert = true }, CancellationToken.None);
}
catch (MongoWriteException mongoWriteException)
{
if (mongoWriteException.WriteError.Category != ServerErrorCategory.DuplicateKey)
{
throw;
}
}
}
private void Update()
{
尝试
{
var find=Builders.Filter.Eq(e=>e.Id,“someId”);
var update=Builders.update.Set(e=>e.SomeValue,“AValue”);
_documentStore.MongoCollection().UpdateOne(查找、更新、新更新选项{isupert=true},CancellationToken.None);
}
捕获(MongoWriteException MongoWriteException)
{
if(mongoWriteException.WriteError.Category!=ServerErrorCategory.DuplicateKey)
{
投掷;
}
}
}
有人知道我如何模仿MongoWriteException吗?我试着这样构造它:
var mongoWriteException = new MongoWriteException(new ConnectionId(new ServerId(new ClusterId(1), new DnsEndPoint("d", 2)), 0), new WriteError(), // <- Protected constructor
var mongoWriteException=new mongoWriteException(new ConnectionId(new ServerId)(new ClusterId(1),new DnsEndPoint(“d”,2)),0),new WriteError(),//您可以使用反射创建具有内部构造函数的类的对象
差不多
var obj = Activator.CreateInstance(typeof(WriteError), true);
ShimsWriteError.AllInstances.Category = errorObj => ServerErrorCategory.DuplicateKey
上述代码中的第二个参数是指定用于查找非公共默认构造函数的激活器
但这样就不能初始化任何值或使用带参数的构造函数
我假设您已经为mogo DB库创建了一个伪程序集,并使用shim模拟UpdateOne方法
如果是这种情况,您可以根据测试用例填充WriteError对象并使属性“Category”返回您想要的任何值
大概是
var obj = Activator.CreateInstance(typeof(WriteError), true);
ShimsWriteError.AllInstances.Category = errorObj => ServerErrorCategory.DuplicateKey
上述代码中的语法可能不同。但想法是相同的。一个基于反射的小示例,但使用反射来获取内部构造函数
static class MockMongoCollection // : IMongoCollection<TDocument>
{
private static readonly MongoWriteException __writeException;
static MockMongoCollection()
{
var connectionId = new ConnectionId(new ServerId(new ClusterId(1), new DnsEndPoint("localhost", 27017)), 2);
var innerException = new Exception("inner");
var ctor = typeof (WriteConcernError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
var writeConcernError = (WriteConcernError)ctor.Invoke(new object[] { 1, "writeConcernError", new BsonDocument("details", "writeConcernError") });
ctor = typeof (WriteError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
var writeError = (WriteError) ctor.Invoke(new object[] {ServerErrorCategory.Uncategorized, 1, "writeError", new BsonDocument("details", "writeError")});
__writeException = new MongoWriteException(connectionId, writeError, writeConcernError, innerException);
}
public static void UpdateOne()
{
throw __writeException;
}
}
class ExampleTests
{
[Test]
public void UncategorizedWriteExceptionTest()
{
Assert.Throws<MongoWriteException>(MockMongoCollection.UpdateOne);
}
}
静态类MockMongoCollection/:IMongoCollection
{
私有静态只读MongoWriteException\uuu writeException;
静态MockMongoCollection()
{
var connectionId=new connectionId(新的ServerId(新的ClusterId(1),新的DnsEndPoint(“localhost”,27017)),2);
var innerException=新异常(“内部”);
var ctor=typeof(WriteConcernError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
var writeConcernError=(writeConcernError)ctor.Invoke(新对象[]{1,“writeConcernError”,新BsonDocument(“详细信息”,“writeConcernError”)});
ctor=typeof(WriteError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
var writeError=(writeError)ctor.Invoke(新对象[]{ServerErrorCategory.Uncategorized,1,“writeError”,新BsonDocument(“详细信息”,“writeError”)});
__writeException=新的MongoWriteException(connectionId、writeError、writeConcernError、innerException);
}
公共静态void UpdateOne()
{
抛出写异常;
}
}
类示例测试
{
[测试]
public void UncategorizedWriteExceptionTest()
{
抛出(MockMongoCollection.UpdateOne);
}
}
还有一个使用SerializationInfo的构造函数,它可能有类似的味道。所以我在这里接受了@logan rakai的答案()并对其进行了一些修改。下面是我的结论
[Test]
public void GivenADuplicateKeyWriteErrorOccurs_WhenCallingUpdateOne_ThenNoExceptionIsThrown()
{
// Given
var someMongoService = CreateSomeObject();
_mockMongoCollection.Setup(x => x.UpdateOne(It.IsAny<FilterDefinition<SomeObject>>(), It.IsAny<UpdateDefinition<SomeObject>>(), It.IsAny<UpdateOptions>(), default(CancellationToken))).Throws(CreateMongoWriteException(ServerErrorCategory.DuplicateKey));
// When / Then
Assert.DoesNotThrow(() => someMongoService.Upsert(new CreateNewSomeObject());
}
[Test]
public void GivenAExceptionOccursWhichIsNotADuplicateKeyWriteError_WhenCallingUpdateOne_ThenTheExceptionIsThrown()
{
// Given
var someMongoService = CreateFilterService();
var exception = CreateMongoWriteException(ServerErrorCategory.ExecutionTimeout);
_mockMongoCollection.Setup(x => x.UpdateOne(It.IsAny<FilterDefinition<SomeObject>>(), It.IsAny<UpdateDefinition<SomeObject>>(), It.IsAny<UpdateOptions>(), default(CancellationToken))).Throws(exception);
// When / Then
Assert.Throws<MongoWriteException>(() => someMongoService.Upsert(new CreateNewSomeObject());
}
public static MongoWriteException CreateMongoWriteException(ServerErrorCategory serverErrorCategory)
{
var connectionId = new ConnectionId(new ServerId(new ClusterId(1), new DnsEndPoint("localhost", 27017)), 2);
var writeConcernError = CreateWriteConcernError();
var writeError = CreateWriteError(serverErrorCategory);
return new MongoWriteException(connectionId, writeError, writeConcernError, new Exception());
}
private static WriteError CreateWriteError(ServerErrorCategory serverErrorCategory)
{
var ctor = typeof (WriteError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
var writeError = (WriteError)ctor.Invoke(new object[] {serverErrorCategory, 1, "writeError", new BsonDocument("details", "writeError")});
return writeError;
}
private static WriteConcernError CreateWriteConcernError()
{
var ctor = typeof(WriteConcernError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
return (WriteConcernError)ctor.Invoke(new object[] { 1, "writeConcernError", new BsonDocument("details", "writeConcernError") });
}
我对mongodb不太熟悉。什么类型是\u documentStore
。我认为您可能需要抽象您对驱动程序的访问权限,因为它还没有。Document store只是一个门面。真正的问题是,我无法模拟异常的发生。它通常会发生在哪里。可能您可以在调用时使用moq抛出它其中一个模拟。我需要能够访问WriteError,它是一个受保护的构造函数,所以这是不可能的。@MarkWalsh,我可以说这是一种不好的方法,但您可以通过反射构造WriteError类型的对象。