使用MOQ验证表达式参数

时间:2013-04-14 05:15:22

标签: c# linq unit-testing expression moq

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

这是受测试的系统

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


}

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

提前致谢。

2 个答案:

答案 0 :(得分:1)

  1. 为您的测试提供一个有意义的名称,以便我们了解您的目标,
  2. 将您的考试安排在三个区域,并按评论或空格分开:

    • 安排,
    • 断言
  3. 这使得行动的内容更加清晰。

    那就是说,在我看来你试图断言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);
        }
    

答案 1 :(得分: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
}