Moq 设置没有返回正确的值
Moq setup is not returning correct value
我查看了其他答案,但尚未找到任何有用的信息。也许我误会了。 GetDocumentCount 模拟不工作。
Class 测试中:
public class DeleteDocument
{
private readonly IMongoClient _mongoClient;
public DeleteDocument(IMongoClient mongoClient)
{
this._mongoClient = mongoClient;
}
public override bool ProcessRequest(DeleteDocumentRequest request)
{
var docObjectIds = request.Ids.Select(ObjectId.Parse).ToArray();
var documents = _mongoClient.GetDocumentsCollection(Constants.DATABASE);
var documentCount = GetDocumentCount(documents, docObjectIds);
if (documentCount != request.Ids.Length)
{
throw new ValidationException(-6, "The document count doesn't match");
}
... more code here
return true;
}
public virtual long GetDocumentCount(IMongoCollection<Document> docs, ObjectId[] objIds)
{
return docs.Find(x => objIds.Contains(x.Id)).CountDocuments();
}
}
单元测试是遗留代码,无法正常工作,我很难理解它是否真的在正确模拟 MongoDb。我还没有找到很多 MongoDb 模拟的好例子。这是完整的单元测试:
[TestMethod]
public void DeleteDocument_DocumentCountDoesNotMatch_ReturnsErrorCode()
{
var mockIMongoCollection = new Mock<IMongoCollection<Document>>();
var asyncCursor = new Mock<IAsyncCursor<Document>>();
var docCollection = new[]
{
// this is the document to delete
new Document
{
CreateDate = DateTime.UtcNow,
Id = new ObjectId("6074d4da433ab6b5a731b82c"),
IsActive = true
}
};
mockIMongoCollection.Setup(collection => collection.FindSync(
Builders<Document>.Filter.Empty,
It.IsAny<FindOptions<Document>>(),
default))
.Returns(asyncCursor.Object);
asyncCursor.SetupSequence(async => async.MoveNext(default))
.Returns(true)
.Returns(false);
asyncCursor.SetupGet(async => async.Current)
.Returns(docCollection);
var mongoDatabaseMock = new Mock<IMongoDatabase>();
mongoDatabaseMock.Setup(x => x.GetCollection<Document>(
It.IsAny<string>(),
It.IsAny<MongoCollectionSettings>()))
.Returns(mockIMongoCollection.Object);
var mongoClientMock = new Mock<IMongoClient>();
mongoClientMock.Setup(x => x.GetDatabase(
It.IsAny<string>(),
It.IsAny<MongoDatabaseSettings>()))
.Returns(mongoDatabaseMock.Object);
var mockClass = new Mock<DeleteDocument>(mongoClientMock.Object)
{ CallBase = true };
mockClass.Setup(
x => x.GetDocumentCount
(It.IsAny<IMongoCollection<Document>>(),
It.IsAny<ObjectId[]>()))
.Returns(Convert.ToInt64(1));
var ex = Assert.ThrowsException<ValidationException>(() =>
new DeleteDocument(mongoClientMock.Object)
.ProcessRequest(new DeleteDocumentRequest(null)
{
Ids = new[] { "6074d4da433ab6b5a731b82c" }
}));
Assert.AreEqual(-6, ex.Code);
}
看来您创建了被测对象的模拟
//...
var mockClass = new Mock<DeleteDocument>(mongoClientMock.Object) { //<-- mocked instance
CallBase = true
};
//...
然后在进行测试时继续使用被测对象的另一个单独实例
//...
var ex = Assert.ThrowsException<ValidationException>(() =>
new DeleteDocument(mongoClientMock.Object) //<-- new instance here
.ProcessRequest(new DeleteDocumentRequest(null)
{
Ids = new[] { "6074d4da433ab6b5a731b82c" }
}));
//...
由于您还想覆盖 GetDocumentCount
的行为,因此在这种边缘情况下的模拟是在执行测试时需要使用的
[TestMethod]
public void DeleteDocument_DocumentCountDoesNotMatch_ReturnsErrorCode() {
//Arrange
//...omitted for brevity
var mockClass = new Mock<DeleteDocument>(mongoClientMock.Object) {
CallBase = true
};
mockClass
.Setup(x => x.GetDocumentCount(It.IsAny<IMongoCollection<Document>>(), It.IsAny<ObjectId[]>()))
.Returns(Convert.ToInt64(99)); //<-- this need to not match request
var request = new DeleteDocumentRequest(null) {
Ids = new[] { "6074d4da433ab6b5a731b82c" }
}
//Act &
Action act = () => mockClass.Object.ProcessRequest(request);
//Assert
ValidationException ex = Assert.ThrowsException<ValidationException>(act);
Assert.AreEqual(-6, ex.Code);
}
我查看了其他答案,但尚未找到任何有用的信息。也许我误会了。 GetDocumentCount 模拟不工作。
Class 测试中:
public class DeleteDocument
{
private readonly IMongoClient _mongoClient;
public DeleteDocument(IMongoClient mongoClient)
{
this._mongoClient = mongoClient;
}
public override bool ProcessRequest(DeleteDocumentRequest request)
{
var docObjectIds = request.Ids.Select(ObjectId.Parse).ToArray();
var documents = _mongoClient.GetDocumentsCollection(Constants.DATABASE);
var documentCount = GetDocumentCount(documents, docObjectIds);
if (documentCount != request.Ids.Length)
{
throw new ValidationException(-6, "The document count doesn't match");
}
... more code here
return true;
}
public virtual long GetDocumentCount(IMongoCollection<Document> docs, ObjectId[] objIds)
{
return docs.Find(x => objIds.Contains(x.Id)).CountDocuments();
}
}
单元测试是遗留代码,无法正常工作,我很难理解它是否真的在正确模拟 MongoDb。我还没有找到很多 MongoDb 模拟的好例子。这是完整的单元测试:
[TestMethod]
public void DeleteDocument_DocumentCountDoesNotMatch_ReturnsErrorCode()
{
var mockIMongoCollection = new Mock<IMongoCollection<Document>>();
var asyncCursor = new Mock<IAsyncCursor<Document>>();
var docCollection = new[]
{
// this is the document to delete
new Document
{
CreateDate = DateTime.UtcNow,
Id = new ObjectId("6074d4da433ab6b5a731b82c"),
IsActive = true
}
};
mockIMongoCollection.Setup(collection => collection.FindSync(
Builders<Document>.Filter.Empty,
It.IsAny<FindOptions<Document>>(),
default))
.Returns(asyncCursor.Object);
asyncCursor.SetupSequence(async => async.MoveNext(default))
.Returns(true)
.Returns(false);
asyncCursor.SetupGet(async => async.Current)
.Returns(docCollection);
var mongoDatabaseMock = new Mock<IMongoDatabase>();
mongoDatabaseMock.Setup(x => x.GetCollection<Document>(
It.IsAny<string>(),
It.IsAny<MongoCollectionSettings>()))
.Returns(mockIMongoCollection.Object);
var mongoClientMock = new Mock<IMongoClient>();
mongoClientMock.Setup(x => x.GetDatabase(
It.IsAny<string>(),
It.IsAny<MongoDatabaseSettings>()))
.Returns(mongoDatabaseMock.Object);
var mockClass = new Mock<DeleteDocument>(mongoClientMock.Object)
{ CallBase = true };
mockClass.Setup(
x => x.GetDocumentCount
(It.IsAny<IMongoCollection<Document>>(),
It.IsAny<ObjectId[]>()))
.Returns(Convert.ToInt64(1));
var ex = Assert.ThrowsException<ValidationException>(() =>
new DeleteDocument(mongoClientMock.Object)
.ProcessRequest(new DeleteDocumentRequest(null)
{
Ids = new[] { "6074d4da433ab6b5a731b82c" }
}));
Assert.AreEqual(-6, ex.Code);
}
看来您创建了被测对象的模拟
//...
var mockClass = new Mock<DeleteDocument>(mongoClientMock.Object) { //<-- mocked instance
CallBase = true
};
//...
然后在进行测试时继续使用被测对象的另一个单独实例
//...
var ex = Assert.ThrowsException<ValidationException>(() =>
new DeleteDocument(mongoClientMock.Object) //<-- new instance here
.ProcessRequest(new DeleteDocumentRequest(null)
{
Ids = new[] { "6074d4da433ab6b5a731b82c" }
}));
//...
由于您还想覆盖 GetDocumentCount
的行为,因此在这种边缘情况下的模拟是在执行测试时需要使用的
[TestMethod]
public void DeleteDocument_DocumentCountDoesNotMatch_ReturnsErrorCode() {
//Arrange
//...omitted for brevity
var mockClass = new Mock<DeleteDocument>(mongoClientMock.Object) {
CallBase = true
};
mockClass
.Setup(x => x.GetDocumentCount(It.IsAny<IMongoCollection<Document>>(), It.IsAny<ObjectId[]>()))
.Returns(Convert.ToInt64(99)); //<-- this need to not match request
var request = new DeleteDocumentRequest(null) {
Ids = new[] { "6074d4da433ab6b5a731b82c" }
}
//Act &
Action act = () => mockClass.Object.ProcessRequest(request);
//Assert
ValidationException ex = Assert.ThrowsException<ValidationException>(act);
Assert.AreEqual(-6, ex.Code);
}