使用新断言扩展XUnit Assert类

时间:2013-04-24 14:42:19

标签: c# extension-methods assert xunit.net

我正在尝试通过添加一些selenium功能扩展xUnit assert方法

namespace MyProject.Web.Specs.PageLibrary.Extensions
{
    public static class AssertExtensions
    {
        public static void ElementPresent(this Assert assert, ...)
        {
            if (...)
            {
                throw new AssertException(...);
            }
        }
    }
}

但是当我尝试使用它时,我得到了这个编译错误。

using MyProject.Web.Specs.PageLibrary.Extensions;    
using Xunit;
...

public void DoSomething()
{
    Assert.ElementPresent(...);
}

错误

Error   5   'Xunit.Assert' does not contain a definition for 'ElementPresent'

有人知道这是可能的还是我出错的地方?

7 个答案:

答案 0 :(得分:11)

编辑2 xUnit 2最终最终将断言移动到一个单独的程序集中。在NuGet上有这个包的编译包和源包,并且Assert类是部分的,因此通过使用包的源仅版本,Assert变得非常容易扩展(在C#中,即)。

修改为了更加完整:xUnit 2删除了此扩展点,并建议使用“'流畅”的扩展方法。断言库。


为了完整起见,这里是"官方"的描述。延伸的方式Assert(令人惊讶的是,尽管布拉德·威尔逊甚至加入了讨论,但根本没有提到过。)

从版本1.5(根据Brad的博客),xUnit.Extensions通过AssertionsTestClass类明确支持此功能。它的工作原理如下:

TestClass有一个名为Assert的属性,类型为Assertions,它会转发Xunit.Assert上的所有方法。由于TestClass.Assert是一个实例,您可以通过Assertions上的扩展方法向其添加方法:

public static class AssertionsExtensions
{
    public static void DeepEquals(this Assertions assertions, XNode expected, XNode actual)
    {
        assertions.True(XNode.DeepEquals(expected, actual)); // You can also use Assert.True here, there's effectively no difference.
    }
}

现在您需要让您的测试类派生自Xunit.Extensions.TestClass(令人困惑的是,还有Xunit.TestClass,这不是您想要的),而Assert属性将为&#34 ;阴影" Xunit.Assert类型,如果您没有明确限定名称。

在源自TestClass的测试类中,您现在可以使用

Assert.DeepEquals(expectedXml, actualXml);

内置xUnit断言的唯一真正区别(除了Assert的语法着色是标识符而不是类型的语法着色)是当它失败时,你只需得到一个{{ 1}},而不是一个特定的TrueException可以假设告诉你哪里比较失败了。但是当然你也可以用同样的方式构建它。

答案 1 :(得分:5)

抱歉,但你感到困惑(编辑:我也是!)。 xUnit.net的Assert static,因此不能添加扩展(尽管其他Assertion库没有采用这种方法,这就是为什么人们可能希望使用扩展方法来扩展Assert )。因此,在xUnit.net Universe中,如果要添加自定义断言,请添加具有不同名称的新静态类。

您可以通过以下方式更改课程来使您的方法有效:

public static class AssertExtensions
{
    public static void ElementPresent(this Assert assert, ...)

为:

public class AssertExtensions : XUnit.Assert
{
    public static void ElementPresent(...)

然后使用@ BradWilson的添加技巧:

using Assert = MyProject.Web.Specs.PageLibrary.Extensions.AssertExtensions; 

位于需要扩展程序的文件的顶部。

这种技术可以方便地添加重载来考虑它....

(明显的弱点是你不能通过Assert.直接访问多个

答案 2 :(得分:5)

xUnit 2 的解决方案摘要。 (为NuGet的2.1.0版本工作。)

Assert是一个部分类,您可以通过添加另一个部分来扩展它。为此,您需要从源代码编译Assert程序集。您可以使用xunit.assert.source NuGet获取源代码。

步骤

  1. 从项目中移除xunit.assert NuGet包的引用。
  2. 而是安装 xunit.assert.source 包。
  3. Xunit命名空间中,定义public partial class Assert并在那里添加自定义断言。
  4. 在您的测试项目中安装xunit.extensibility.execution包(否则两个不同的Assert类之间会发生冲突,并且由于xunit.execution.*.dll将丢失,测试将无法运行< / LI>

    自定义断言的示例:

    namespace Xunit
    { 
        public partial class Assert
        {
            public static void ArraySegmentEqual<T>(
                T[] expectedSequence, T[] buffer, int offset = 0)
            {
                for (int i = 0; i < expectedSequence.Length; i++)
                {
                    int b = i + offset;
    
                    True(buffer[b].Equals(expectedSequence[i]),
                        $"Byte #{b} differs: {buffer[b]} != {expectedSequence[i]}");
                }
            }
        }
    }
    

    注意:其他答案和编辑也指向解决方案,但我花了很多时间从那里弄清楚它。此外,我并不认为这是唯一或最佳选择。

答案 3 :(得分:3)

您需要将对象intance作为此参数传递给extension方法。 在你的情况下,这将是正确的语法

var assert = new Assert();
assert.ElementPresent(...);

但我想你不需要甚至不能创建Assert类的实例。

您要做的是将扩展方法调用为扩展类上的静态调用,并且不起作用。 但为什么不简单地打电话

 AssertExtensions.ElementPresent(...);

答案 4 :(得分:0)

xUnit 2 +

1)将xunit.assert.source Nuget包添加到带扩展名的项目中。

2)创建部分类定义:

namespace xUnit
{
  public partial class Assert
  {
    public static void ElementPresent(...)
    {
    }
  }
}

答案 5 :(得分:0)

问题是由于简单的封装约束:

由于Assert类的构造函数设置为protected,因此您无法为其创建Extension Method,因为您无法实例化它。

因此,要扩展Assert,您只需要继承即可:

public class MyExtendedAssert : Assert
{
    public void ElementPresent(...)
    {
        ...
    }
}

并使用:

MyExtendedAssert.ElementPresent(...);

答案 6 :(得分:0)

我使用一个简单的partial助手,在其中添加了That属性,以便可以在其他任何地方轻松构建扩展名:

// ReSharper disable once CheckNamespace
namespace Xunit
{
    public partial class Assert
    {
        [CanBeNull]
        public static Assert That => default;
    }
}

阅读Premil's回答如何设置项目。

相关问题