使用MOQ验证表达式参数

5
我正在尝试验证我测试的方法是否已经使用特定表达式调用。我已经花费了数小时的时间,但没有得到我想要的结果。
这是被测试的系统。
public class sut
{
    private IEntityUtil _ew;
    public sut(IEntityUtil ew)
    {
        _ew = ew;
    }

    public void Search()
    {
        Guid id = Guid.Parse("CB594050-3845-4EAF-ABC5-34840063E94F");
        var res = _ew.SelectSingle<Post>(w => w.Id == id, new PersonalSiteEntities());
    }

}

这是依赖关系

public interface IEntityUtil
{
    TEntity SelectSingle<TEntity>(Expression<Func<TEntity, bool>> predicate, System.Data.Objects.ObjectContext ctx)
        where TEntity : EntityObject;
    List<TEntity> SelectList<TEntity>(Expression<Func<TEntity, bool>> predicate, System.Data.Objects.ObjectContext ctx)
        where TEntity : EntityObject;
    bool Insert<TEntity>(TEntity entity, System.Data.Objects.ObjectContext ctx)
        where TEntity : EntityObject;
}

我正在尝试测试它的方式如下:

  public class tst
{
    [TestMethod]
    public void tst1()
    {
        var cwMock = new Mock<ConsoleApplication1.IEntityUtil>();

        Guid id = Guid.Parse("CB594050-3845-4EAF-ABC5-34840063E94F");

        //cwMock.Setup(x => x.SelectSingle<ConsoleApplication1.Post>(w => w.Id == id, It.IsAny<System.Data.Objects.ObjectContext>())).Returns(new ConsoleApplication1.Post()).Verifiable();


        //cwMock.Setup(x => x.SelectSingle(It.IsAny<Expression<Func<ConsoleApplication1.Post, bool>>>(), It.IsAny<System.Data.Objects.ObjectContext>())).Returns(new ConsoleApplication1.Post()).Verifiable();


        Expression<Func<ConsoleApplication1.Post, bool>> func = (param) => param.Id == id;

        cwMock.Setup(x => x.SelectSingle<ConsoleApplication1.Post>(func, It.IsAny<System.Data.Objects.ObjectContext>())).Returns(new ConsoleApplication1.Post());

        var sut = new ConsoleApplication1.sut(cwMock.Object);

        sut.Search();

        //cwMock.VerifyAll();

        cwMock.Verify(x => x.SelectSingle(func, It.IsAny<System.Data.Objects.ObjectContext>()));
    }


}

请注意,第二个注释设置将使测试通过,但它不允许我验证是否传递了特定的表达式。
提前感谢。

那么你的结果是什么?问题出在哪里?Moq执行不正确吗? - Mic
2个回答

1

两个可以极大地帮助我们的事情是:

  1. 给你的测试起一个有意义的名字,这样我们就知道你想要什么,
  2. 将你的测试分成三个部分,并通过注释或空格进行分隔:

    • 安排(Arrange),
    • 行动(Act),
    • 断言(Assert)

这使得行动更加清晰。

话虽如此,我觉得你试图断言在调用 sut.Search() 时是否只调用了一次 ew.SelectSingle

另外,我注意到你在测试中创建了 Guid,但从未对其进行任何操作。因此,这是你测试的一个快速建议(不使用 IDE,因此可能会出现错误):

    [Fact]
    public void Verify_SelectSingle_IsCalledOnce( ){

        Guid id = Guid.Parse( "CB594050-3845-4EAF-ABC5-34840063E94F" );
        var cwMock = new Mock<ConsoleApplication1.IEntityUtil>( );
        var post = new ConsoleApplication1.Post{ Id = id };
        cwMock
          .Setup( x=> x.SelectSingle<ConsoleApplication1.Post>(It.IsAny<Guid> ))
          .Returns( post );
        var sut = new ConsoleApplication1.sut(cwMock.Object);



        sut.Search();



        cwMock.Verify( 
          x=> x.SelectSingle( It.IsAny<ObjectContect>( o => o.Id == id )), 
          Times.Once);
    }

0

正如已经指出的那样,很难确定您试图实现的确切目标,因为您没有明确说明测试名称。 话虽如此,看起来您需要向模拟设置提供一个回调函数,以便允许您验证表达式。 像这样的东西应该有所帮助(使用注释掉的通过设置):

cwMock.Setup(x => x.SelectSingle(It.IsAny<Expression<Func<ConsoleApplication1.Post, bool>>>(), It.IsAny<System.Data.Objects.ObjectContext>())).Callback<Expression<Func<ConsoleApplication1.Post, bool>>>(VerifyExpression).Returns(new ConsoleApplication1.Post()).Verifiable();

然后创建一个回调方法

private static void VerifyExpression(Expression<Func<ConsoleApplication1.Post, bool>> expression)
{
    var func = expression.Compile();
    // call func(params) and verify against it
}

那么你如何检查这个表达式呢?我遇到了麻烦,例如:func.Should().BeEquivalentTo<Expression<Func<Country, object>>>(c => c.Locales); 但是这并不起作用(会抛出异常)。 - Roelant M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接