简体   繁体   English

单元测试保存更改失败

[英]Unit Test Save Changes failing

Frameworks 构架

.NETCoreApp 1.1
EF Core 1.1.1
Xunit 2.2.0
Moq 4.7.8

Controller Post Method 控制器发布方法
_yourRepository is injected in the controllers constructor and is of type IYourRepository _yourRepository注入到controller构造函数中,类型为IYourRepository

[HttpPost(Name = "CreateMethod")]
public async Task<IActionResult> CreateMethod([FromBody] ObjectForCreationDto objectDto)
{
    if (objectDto== null)
    {
        return BadRequest();
    }

    if (!ModelState.IsValid)
    {
        return BadRequest();
    }

    await _yourRespository.CreateObject(objectDto);

    if (!await _yourRespository.Save())
    {
        throw new Exception("Creating this object failed on save.");
    }            

    return Ok();
}

Unit Test that fails 单元测试失败

[Fact]
public async Task CreateObject_WhenGoodDtoReceived_SuccessStatusReturned()
{
    // Arrange
    var mockRepo = new Mock<IYourRepository>();
    var controller = new YourController(mockRepo.Object);
    var objectForCreationDto = new ObjectForCreationDto { Code = "0001", Name = "Object One" };

    // Act
    var result = await controller.CreateObject(objectForCreationDto);

    // Assert
    Assert.IsType<OkObjectResult>(result);
}

The test fails because the line 测试失败是因为线路

if (!await _yourRespository.Save())

Always evaluates to true. 始终评估为true。 When it evaluates to true you can see that the code throws an error (which is handled by middleware) 当它的计算结果为true时,您可以看到代码抛出错误(由中间件处理)

_yourRepository.Save() method _yourRepository.Save()方法

public async Task<bool> Save()
{
    return (await _yourContext.SaveChangesAsync() >= 0);
}

I'm not sure how to solve the problem and I'm not 100% sure why it is failing. 我不知道如何解决这个问题,我不能100%肯定它为什么会失败。

Is it because the mocked IYourRepository interface doesn't include an implementation of the Save method? 是因为IYourRepository接口不包含Save方法的实现吗?

If so, does that mean to test the Post method I would need to mock my DbContext and construct my YourRepository object using it? 如果是这样,这是否意味着测试Post方法我需要模拟我的DbContext并使用它构造我的YourRepository对象?

Any explanation as to why this is failing and how to rectify it would be much appreciated 关于为什么失败以及如何纠正它的任何解释将非常感激

You need to setup the repo to return a proper task from the async method. 您需要设置repo以从异步方法返回正确的任务。 Moq allows this using ReturnsAsync Moq允许使用ReturnsAsync

[Fact]
public async Task CreateObject_WhenGoodDtoReceived_SuccessStatusReturned()
{
    // Arrange
    var mockRepo = new Mock<IYourRepository>();
    mockRepo.Setup(_ => _.Save()).ReturnsAsync(true);//<-- ADD THIS
    var controller = new YourController(mockRepo.Object);
    var objectForCreationDto = new ObjectForCreationDto { Code = "0001", Name = "Object One" };

    // Act
    var result = await controller.CreateObject(objectForCreationDto);

    // Assert
    Assert.IsType<OkObjectResult>(result);
}

Replace new Mock<IYourRepository>(); 替换new Mock<IYourRepository>(); with new Mock<IYourRepository>(MockBehavior.Strict); 使用new Mock<IYourRepository>(MockBehavior.Strict); - now it will throw exceptions when any method without Setup is called. - 现在,当调用没有Setup任何方法时,它将抛出异常。

Obviously, you should not check (assert) something (like return values) you do not determined. 显然,你不应该检查(断言)你没有确定的东西(比如返回值)。

Mock Save method returns false by default. Mock Save方法默认返回false You need to explicitly setup true as return value: 您需要显式设置true作为返回值:

mockRepo.Setup(x => x.Save()).Returns(Task<bool>.FromResult(true));

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

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