【问题标题】:Mocked method still returns null模拟方法仍然返回 null
【发布时间】:2017-01-18 14:49:47
【问题描述】:

在我的新 .Net Core 项目中,我决定第一次使用 Moq 框架。根据教程设置所有方法后,我仍然收到异常:

"The following setups were not matched: IRepository`1 cr => cr.GetSingle(x => x.Key == 7028750f-044c-4862-999d-e21c4bfe7543) "

或者在删除所有 VerifyAll() 调用后,a 从服务中获取 null。 知道如何解决吗?

依赖:

  • “Microsoft.NETCore.App”:“1.1.0”,
  • “起订量”:“4.6.38-alpha”,
  • “xunit”:“2.2.0-beta5-build3474”,
  • “dotnet-test-xunit”:“2.2.0-preview2-build1029”,

人物:

public class Character : IEntity
{
    ...
    public Guid Key { get; set; }
    ...
}

通用存储库:

public interface IRepository<TEntity> where TEntity : class, IEntity
{
    TEntity GetSingle(Expression<Func<TEntity, bool>> predicate);
    ...
}

工作单元:

public interface IUnitOfWork
{        
    IRepository<TEntity> Repository<TEntity>() where TEntity : class, IEntity;       
    ...
}

字符服务:

class CharactersService : ICharactersService
{
    private readonly IUnitOfWork _unitOfWork;

    public CharactersService(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public Character GetCharacterByKey(Guid characterKey)
    {
        var charactersRepository = _unitOfWork.Repository<Character>();
        var character = charactersRepository.GetSingle(ch => ch.Key == characterKey);
        return character;
    }
    ...
}

测试类:

public class CharactersServiceTest
{
    [Fact]
    public void GetCharacterByKey_CharacterExists_ReturnsCharacter()
    {
        //Arrange
        var guid = Guid.NewGuid();
        var characterFromDb = new Character { Key = guid };

        var characterRepositoryMock = new Mock<IRepository<Character>>();
        characterRepositoryMock.Setup(cr => cr.GetSingle(x => x.Key == guid)).Returns(characterFromDb);
        characterRepositoryMock.VerifyAll();

        var unitOfWorkMock = new Mock<IUnitOfWork>();
        unitOfWorkMock.Setup(uow => uow.Repository<Character>()).Returns(characterRepositoryMock.Object);
        unitOfWorkMock.VerifyAll();

        var charactersService = new CharactersService(unitOfWorkMock.Object);

        //Act
        var character = charactersService.GetCharacterByKey(guid);

        //Assert
        Assert.NotNull(character);
    }
}

【问题讨论】:

  • 我很确定您应该在测试完成后调用VerifyAll,以验证您的期望在测试期间是否得到满足...
  • 我同意@Will 的观点,VerifyAll 方法用于验证为该模拟类设置的所有期望值是否已得到满足。因此,您设置的任何方法都可能希望验证它是否已被正确调用,因此 VerifyAll 函数是一个帮助器,因此您不必为您希望进行的每个验证调用它。

标签: c# .net moq


【解决方案1】:

这里的问题是,你比较两个表达式:

首先在characterRepositoryMock.Setup : x =&gt; x.Key == guid
第二个在GetCharacterByKey 方法:ch =&gt; ch.Key == characterKey

它们不相同,因为它们指向两个不同的 Expression 对象。 如果您真的想以这种方式进行测试,您应该检查两个表达式是否获得相同的 GUID 值:

characterRepositoryMock.Setup(cr => 
  cr.GetSingle(It.Is<Expression<Func<Character, bool>>>(x =>check(x, guid)) ))
 .Returns(characterFromDb);

用这种检查方法:

public bool check(Expression<Func<Character,bool>> x, Guid guid)
{
    var body = x.Body as BinaryExpression;  
    var g = (Guid) Expression.Lambda(body.Right).Compile().DynamicInvoke(); 
    return g == guid;
}

而且,是的,我同意 cmets,VerifyAll 应该被称为 毕竟,在断言部分。

【讨论】:

  • 如果您没有在设置语句中添加.Verifiable()VerifyAll() 不会为您做任何事情。
猜你喜欢
  • 1970-01-01
  • 2011-09-30
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多