简体   繁体   English

单元测试 mongoDb with .net core

[英]Unit Test mongoDb with .net core

I am trying to write down unit test for my repository which is interacting with MongoDb but facing a problem/exception in mocking the objects.我正在尝试为与 MongoDb 交互但在 mocking 对象中遇到问题/异常的存储库写下单元测试。 This is what I have tried so far;到目前为止,这是我尝试过的;

This is how my class looks like ie I have create a repository class and extend it from interface;这就是我的 class 的样子,即我已经创建了一个存储库 class 并从界面扩展它;

public class UserManagementRepository : IUserManagementRepository
{
    private readonly IMongoCollection<UserModel> _users;
    public UserManagementRepository(IDatabaseSettings dbSettings, IApplicationSettings applicationSettings, IMongoClient mongoClient)
    {
        IMongoDatabase database = mongoClient.GetDatabase(dbSettings.DatabaseName);
        _users = database.GetCollection<UserModel>(applicationSettings.UserCollectionName);
    }
    
    public async Task<GeneralResponse> Get(string id)
    {
        GeneralResponse response = new GeneralResponse();
        try
        {
            IAsyncCursor<UserModel> userModel = await _users.FindAsync(user => user.Id == id);
            if (userModel != null)
            {
                response.Message = "User exists!";
                response.Data = userModel.FirstOrDefault();
                response.ResponseCode = ResponseCode.Success;
            }
            else
            {
                response.Message = $"User with Id: {id} not found!";
                response.ResponseCode = ResponseCode.Success;
            }
        }
        catch (Exception ex)
        {
            response.Message = "Failure";
            response.ResponseCode = ResponseCode.Error;
        }
        return response;
    }
}

This is how my Test class look like这就是我的测试 class 的样子

public class UserManagmentRepositoryTests
{
    private Mock<IDatabaseSettings> _mockDbSettings;
    private Mock<IApplicationSettings> _mockApplicationSettings;
    private Mock<IMongoClient> _mockClient;
    public UserManagmentRepositoryTests()
    {
        _mockDbSettings = new Mock<IDatabaseSettings>();
        _mockApplicationSettings = new Mock<IApplicationSettings>();
        _mockClient = new Mock<IMongoClient>();
    }

    [Fact]
    public async Task GetUserWithId_Test()
    {
        // Arrange
        var repo = new Mock<IUserManagementRepository>();
        IDatabaseSettings dbSettings = new DatabaseSettings()
        {
            ConnectionString = "mongodb:connectionstring",
            DatabaseName = "dbname"
        };
        _mockDbSettings.Setup(x => x).Returns(dbSettings);

        IApplicationSettings applicationSettings = new ApplicationSettings() { UserCollectionName = "users" };
        _mockApplicationSettings.Setup(app => applicationSettings).Returns(applicationSettings);

        MongoClientSettings clientSettings = MongoClientSettings.FromConnectionString(dbSettings.ConnectionString);
        MongoClient client = new MongoClient(clientSettings);
        _mockClient.Setup(c => client);

        var ctr = new UserManagementRepository(_mockDbSettings.Object, _mockApplicationSettings.Object, _mockClient.Object);

        // Act
        var result = ctr.Get("132");

        // Assert
        //result.StatusCode.Should().NotBeNull();
    }
}

I get an exception on every setup我在每次设置时都会遇到异常

例外

You are trying to use ApplicationSettings as an expression.您正在尝试将ApplicationSettings用作表达式。 The setup method expects you to provide an expression for when to activate the mocked override. setup 方法希望您提供一个表达式来说明何时激活模拟覆盖。

In your case just get rid of the Mock<IApplicationSettings> altogether and mock all the objects you need to call any methods on:在您的情况下,只需完全摆脱Mock<IApplicationSettings>并模拟您需要调用任何方法的所有对象:

[Fact]
public async Task GetUserWithId_Test()
{
  // Arrange
  var userModel = new UserModel() { Id = "123" };

  var mockCursor = new Mock<IAsyncCursor<UserModel>>();
  mockCursor
    .Setup(c => c.FirstOrDefault())
    .Returns(userModel);

  var mockCollection = new Mock<IMongoCollection<UserModel>>();
  Predicate<UserModel> filter = u => u.Id == userModel.Id;
  mockCollection
    .Setup(c => c.FindAsync(filter))
    .ReturnsAsync(mockCursor.Object);

  var mockDb = new Mock<IMongoDatabase>();
  mockDb
    .Setup(db => db.GetCollection<UserModel>(It.IsAny<string>()))
    .Returns(mockCollection.Object);

  _mockClient
    .Setup(c => c.GetDatabase(It.IsAny<string>()))
    .Returns(mockDb.Object)

  var ctr = new UserManagementRepository(new(), new(), _mockClient.Object);

  // Act
  var result = ctr.Get("132");

  // Assert
  result.StatusCode.Should().Be(ResponseCode.Success);
  result.Message.Should().Be("User exists!");
  result.Data.Should().Be(userModel);
}

Hope this helps a little希望这有所帮助

To use your ApplicationSettings as mocked ApplicationSettings, you must use an expression in the setup method.要将您的 ApplicationSettings 用作模拟的 ApplicationSettings,您必须在设置方法中使用表达式。

Instead of:代替:

    IApplicationSettings applicationSettings = new ApplicationSettings() { UserCollectionName = "users" };
    _mockApplicationSettings.Setup(app => applicationSettings).Returns(applicationSettings);

Use eg this:使用例如:

    IApplicationSettings applicationSettings = new ApplicationSettings() { UserCollectionName= "users" };
    _mockApplicationSettings.Setup(app => app.UserCollectionName).Returns(applicationSettings.UserCollectionName);

Edit: Complete Example编辑:完整示例

    private Mock<IDatabaseSettings> _mockDbSettings;
    private Mock<IApplicationSettings> _mockApplicationSettings;
    private Mock<IMongoClient> _mockClient;
    public UserManagmentRepositoryTests()
    {
        _mockDbSettings = new Mock<IDatabaseSettings>();
        _mockApplicationSettings = new Mock<IApplicationSettings>();
        _mockClient = new Mock<IMongoClient>();
    }

    [Fact]
    public async Task GetUserWithId_Test()
    {
        // Arrange
        var repo = new Mock<IUserManagementRepository>();
        IDatabaseSettings dbSettings = new DatabaseSettings()
        {
            ConnectionString = "mongodb:connection",
            DatabaseName = "dbname"
        };
        _mockDbSettings.Setup(x => x.ConnectionString).Returns(dbSettings.ConnectionString);
        _mockDbSettings.Setup(x => x.DatabaseName).Returns(dbSettings.DatabaseName);

        IApplicationSettings applicationSettings = new ApplicationSettings() { UserCollectionName = "users" };
        _mockApplicationSettings.Setup(app => app.UserCollectionName).Returns(applicationSettings.UserCollectionName);

        MongoClientSettings clientSettings = MongoClientSettings.FromConnectionString(dbSettings.ConnectionString);
        MongoClient client = new MongoClient(clientSettings);
        _mockClient.Setup(c => c.GetDatabase(It.IsAny<string>(), It.IsAny<MongoDatabaseSettings>()))
                    .Returns <string, MongoDatabaseSettings>((name, settings) => client.GetDatabase(name, settings));

        var ctr = new UserManagementRepository(_mockDbSettings.Object, _mockApplicationSettings.Object, _mockClient.Object);

        // Act
        var result = await ctr.Get("132");

        // Assert
        result.ResponseCode.Should().NotBe(ResponseCode.Error);
    }

I see no reason mocking IApplicationSettings and IDatabaseSettings you should go with:我认为没有理由 mocking IApplicationSettings 和 IDatabaseSettings 你应该 go 与:

 public class UserManagmentRepositoryTests
{
    private Mock<IMongoClient> _mockClient;
    public UserManagmentRepositoryTests()
    {
        _mockClient = new Mock<IMongoClient>();
    }

    [Fact]
    public async Task GetUserWithId_Test()
    {
        // Arrange
        var repo = new Mock<IUserManagementRepository>();
        IDatabaseSettings dbSettings = new DatabaseSettings()
        {
            ConnectionString = "mongodb:connectionstring",
            DatabaseName = "dbname"
        };

        IApplicationSettings applicationSettings = new ApplicationSettings() { UserCollectionName = "users" };

        MongoClientSettings clientSettings = MongoClientSettings.FromConnectionString(dbSettings.ConnectionString);
        MongoClient client = new MongoClient(clientSettings);
        _mockClient.Setup(c => client);

        var ctr = new UserManagementRepository(dbSettings, applicationSettings, _mockClient.Object);

        // Act
        var result = ctr.Get("132");

        // Assert
        //result.StatusCode.Should().NotBeNull();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM