模拟方法仍然 returns null

Mocked method still returns null

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

"以下设置不匹配: IRepository`1 cr => cr.GetSingle(x => x.Key == 7028750f-044c-4862-999d-e21c4bfe7543) "

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

依赖关系:

字符:

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;
    }
    ...
}

测试class:

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);
    }
}

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

characterRepositoryMock.Setup 中排名第一:x => x.Key == guid
GetCharacterByKey 方法中的第二个:ch => 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;
}

而且,是的,我同意评论,VerifyAll 应该在 之后被称为 ,在断言部分。