如何模拟IMongoCollection <t>类型的MongoDB集合以返回一些预定义的数据?

时间:2019-04-05 01:17:24

标签: mongodb asp.net-core c#-4.0

下面是我的代码:

控制器/操作:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(CustomerViewModel model, string returnUrl = null)
{
    try
    {
        ViewData["ReturnUrl"] = returnUrl;

        // when debugging the test, _dbContext.Customers throws exception
        CustomerDoc existingCustomer = await _dbContext.Customers.Find(o => o.email == model.email).FirstOrDefaultAsync();
        if (existingCustomer != null)
        {
            ModelState.AddModelError("Email", "email already used.");
        }
        // other checkings 

        if (!ModelState.IsValid)
        {
            return View(model);
        }

        // if model state is valid, do something here
    }
    catch (Exception ex)
    {
        return View(model);
    }

    return View(model);
}  

我的单元测试代码是:

[Fact]
public async Task should_return_view_with_errors_when_email_already_exists()
{
    IEnumerable<CustomerDoc> customers = new List<CustomerDoc>
    {
        new CustomerDoc
        {
            email = "test@test.com"
        }
    };

    _dbContextMock.SetupAllProperties();

    // below line is causing the error
    _dbContextMock.Setup(c => c.Customers).Returns(() =>(IMongoCollection<CustomerDoc>)customers);

    CustomerViewModel model = new CustomerViewModel
    {
        email = "test@test.com"
    };

    CreateController();

    var result = await _controller.Register(model);

    Assert.IsType<ViewResult>(result);
    Assert.False(_controller.ModelState.IsValid);
    Assert.True(_controller.ModelState.ContainsKey("Email"));
}

正如您在我的单元测试代码注释中看到的那样,我试图模拟IMongoCollection以返回一些数据。但是我不能这样做,因为 _dbContext.Customers 抛出异常。

如何模拟 IMongoCollection 以返回一些预定义的数据?

我正在使用
asp.net core 2.1.0
mongodb驱动程序2.7.0

1 个答案:

答案 0 :(得分:0)

您将customers声明为List

IEnumerable<CustomerDoc> customers = new List<CustomerDoc>

,然后尝试将其投射到IMongoCollection

() =>(IMongoCollection<CustomerDoc>)customers

有两个直接的指导(但都需要进一步解决):

1)只返回列表,不进行强制转换

() => customers

但是我看不到c.Customers的类型,因此我怀疑这只会解决问题。我会猜测是IMongoCollection<CustomerDoc>,这就是为什么您首先尝试进行演员表转换的原因?这是有问题的,因为.Returns将需要与执行与c.Customer.Find()等效的功能相关联。即便如此,它可能比其他方法要好。

2)将customers变量更改为实现IMongoCollection的类型。

选择1感觉就像是要走的路,因为选择2迫使您开始处理许多实际上与本段代码无关的逻辑。