C# 单元测试保存更改失败

C# 单元测试保存更改失败,c#,asp.net-core,moq,entity-framework-core,xunit2,C#,Asp.net Core,Moq,Entity Framework Core,Xunit2,框架 .NETCoreApp 1.1 EF Core 1.1.1 Xunit 2.2.0 Moq 4.7.8 [Fact] public async Task CreateObject_WhenGoodDtoReceived_SuccessStatusReturned() { // Arrange var mockRepo = new Mock<IYourRepository>(); var controller = new YourController(m

框架

.NETCoreApp 1.1
EF Core 1.1.1
Xunit 2.2.0
Moq 4.7.8
[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);
}
控制器Post方法
\u yourRepository
被注入控制器构造函数,类型为
IYourRepository

总是计算为真。当它的计算结果为true时,您可以看到代码抛出一个错误(由中间件处理)

\u yourRepository.Save()方法

public async Task<bool> Save()
{
    return (await _yourContext.SaveChangesAsync() >= 0);
}
公共异步任务保存()
{
return(wait_yourContext.savechangessync()>=0);
}
我不确定如何解决这个问题,也不确定为什么它会失败

是因为模拟的
IYourRepository
接口没有包含
Save
方法的实现吗

如果是这样,这是否意味着要测试我需要模拟DbContext并使用它构建我的
YourRepository
对象的
Post
方法

如果您能解释为什么会失败以及如何纠正,我们将不胜感激

替换
new Mock()带有
新的Mock(MockBehavior.Strict)-现在,当调用任何不带
Setup
的方法时,它将抛出异常


显然,您不应该检查(断言)未确定的内容(如返回值)。

Mock
Save
方法默认返回
false
。您需要将
true
显式设置为返回值:

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

您需要设置repo以从异步方法返回正确的任务。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);
}
[事实]
公共异步任务CreateObject_WhengoodToReceived_SuccessStatusReturned()
{
//安排
var mockRepo=new Mock();

mockRepo.Setup(=>\uu.Save()).ReturnsAsync(true);//而不是
Wait\u yourRepository.Save()
try
\u yourRepository.Save().Wait()
他在使用mock,\u yourRepository没有任何功能。这就是mock的全部意义,不是有一个具体的实现,而是“伪造”结果你想让它返回谢谢你快速的回答。我还在努力想办法解决这个问题。如果我像这样测试post方法,不意味着我没有真正检查它是否有效吗?我可以通过任何测试(假设它是正确的Dto)测试将通过??或者正在测试应该保存的保存行为(没有双关语!)对于集成测试?这只是测试控制器的
CreateMethod
方法的一个特定场景。我们模拟依赖项以单独执行测试中的方法。@GreenyMcDuff:您正在测试控制器操作,而不是存储库。这就是您模拟存储库以返回所需值的原因。例如如果您想看到操作返回OkObjectResult,您可以模拟
Save()
以返回true。如果您想测试它是否引发异常,您可以模拟
Save()
以返回
false
以模拟db错误,而不使用db/DbContext本身。这就是模拟和单元测试的要点(单元测试的意思是:测试一个单元)(方法、类、属性)而不使用外部依赖项。无论测试是否关闭,因为在控制器操作中,您正在进行ModelState验证(
ModelState.IsValid
),我不确定这是否有效,除非您执行集成测试(使用
TestServer
类),因为在不使用默认控制器的情况下手动实例化
YourController
类时,可能无法设置所需的服务Activator@Tseng谢谢,这解释得更清楚一点。同意你的
ModelState.IsValid
观点。为了测试我刚才使用了
controller.ModelState.addmodeleror(“错误”,“模型错误”);
在另一个测试中
mockRepo.Setup(x => x.Save()).Returns(Task<bool>.FromResult(true));
[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);
}