【问题标题】:Using MOQ to verify expression parameter使用 MOQ 验证表达式参数
【发布时间】:2013-04-06 10:30:48
【问题描述】:

我正在尝试验证我测试的方法是否已使用特定表达式调用。我花了几个小时没有得到我想要的结果。

这是被测系统

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


}

请注意,第二个注释设置将使测试通过,但它不会让我验证是否已传入特定表达式。

提前致谢。

【问题讨论】:

  • 那么你的结果是什么?问题出在哪里?起订量是否执行不正确?

标签: c# linq unit-testing expression moq


【解决方案1】:

有两件事会大有帮助(我们帮助你)

  1. 给你的测试起一个有意义的名字,这样我们就知道你在追求什么,
  2. 将您的测试分为三个区域,并用 cmets 或空格分隔:

    • 安排,
    • 行动,
    • 断言

这样可以更清楚地了解操作是什么。

也就是说,在我看来,您试图断言 ew.SelectSingle 在调用 sut.Search() 时被调用过一次?

我还注意到您在测试中创建了 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);
    }

【讨论】:

    【解决方案2】:

    如前所述,由于您没有明确说明您的测试名称,因此很难准确说出您要完成的工作。也就是说,您似乎需要为您的模拟设置提供一个回调,以允许您验证表达式。像这样的东西应该可以帮助你(使用通过的注释掉的设置):

    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&lt;Expression&lt;Func&lt;Country, object&gt;&gt;&gt;(c =&gt; c.Locales);,但这不起作用。 (抛出异常)
    猜你喜欢
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 2011-06-24
    • 2012-11-09
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多