XUnit Assert class extension with new claims

I am trying to extend the xUnit approval method by adding some selenium functions

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

But I get this compilation error when I try to use it.

 using MyProject.Web.Specs.PageLibrary.Extensions; using Xunit; ... public void DoSomething() { Assert.ElementPresent(...); } 

And mistake

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

Does anyone know if this is possible or where I am wrong?

+8
source share
7 answers

You need an intance object that will be passed as this argument to the extension method. In your case, it will be the correct syntax

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

But I suppose you do not need or cannot even create an instance of the Assert class.

What you are trying to do is call extension method as a static call in an extended class, and this will not work. But why not just call

  AssertExtensions.ElementPresent(...); 
+3
source

Edit 2 xUnit 2 eventually completely moved the statements to a separate assembly. NuGet only has compiled and source packages, and the Assert class is partial, so using the original version of the package, Assert becomes very easily extensible (in C #, that is).

Change For completeness: xUnit 2 removes this extension point and recommends using extension methods in the strings of β€œfree” claim libraries.


For completeness, here is a description of the β€œofficial” way to extend Assert (which is surprisingly not mentioned at all, despite the fact that Brad Wilson even joined the discussion).

In version 1.5 (according to Brad's blog) xUnit.Extensions has explicit support for this through the Assertions and TestClass . It works as follows:

TestClass has an Assert property, which is of type Assertions , which passes all methods to Xunit.Assert . Since TestClass.Assert is an instance, you can add methods to it using extension methods on 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 effectively no difference. } } 

Now you need to get your test class from Xunit.Extensions.TestClass (confused, there is also Xunit.TestClass , which is not what you want), and the Assert property will "shade" like Xunit.Assert , unless you explicitly qualify this name .

In your test class, which is derived from TestClass , you can now use

 Assert.DeepEquals(expectedXml, actualXml); 

The only real difference from the built-in xUnit statement (except that the syntax coloring for Assert is an identifier, not a type) is that when it fails, you just get a TrueException , not a specific DeepEqualsException , which could hypothetically tell you where the comparison failed. But of course, you could build this too.

+11
source

Sorry, but you get confused (EDIT: me too!). xUnit.net Assert is static and therefore extensions cannot be added (although other Assertion libraries do not consider this approach, so extension methods for the Assert extension could be used). Therefore, in the xUnit.net universe, if you want to add your own statement, add a new static class with a different name.

You can make your approach work by changing your class:

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

in

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

and then using the @BradWilson add-on trick:

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

at the top of any file that requires your extensions.

This method is convenient for adding overloads to think about it ....

(The obvious weakness is that you cannot have more than one available through Assert. , Though)

+5
source

Solution summary for xUnit 2 . (Worked for me for version 2.1.0 from NuGet.)

Assert is a partial class that you can extend by adding another part. To do this, you need to compile the Assert assembly from the source. You can use xunit.assert.source NuGet to get the source xunit.assert.source .

Steps

  1. Remove the link to xunit.assert NuGet xunit.assert from the project.
  2. Instead, install the xunit.assert.source package.
  3. In the Xunit namespace Xunit define a public partial class Assert and add your custom statements there.
  4. In your test project, install the xunit.extensibility.execution package (otherwise there will be a conflict between the two different Assert classes and the tests will not run due to the absence of xunit.execution.*.dll )

Example user statement:

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

Note. Other answers and edits also indicate a solution, but it took me a long time to figure it out from there. In addition, I am not saying that this is the only or best option.

+5
source

For xUnit 2 + :

1) Add the xunit.assert.source package to the project with extensions.

2) Create a partial class definition:

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

The problem is simply restricting encapsulation:

Since the Assert class has a constructor, protected you cannot create an Extension Method for it, because you cannot create an instance of it.

So, to extend Assert , you just need to inherit from it:

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

And use:

 MyExtendedAssert.ElementPresent(...); 
0
source

I use a simple partial helper where I add the That property so that I can easily create extensions anywhere:

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

Read Premil's answer on how to set up projects.

0
source

All Articles