NSubstitute Swap Method

I want to make the mock extension method, but it does not work. How can this be done?

public static class RandomExtensions { public static IEnumerable<int> NextInt32s(this System.Random random, int neededValuesNumber, int minInclusive, int maxExclusive) { // ... } } 

 [Fact] public void Select() { var randomizer = Substitute.For<DefaultRandom>(); randomizer.NextInt32s(3, 1, 10).Returns(new int[] { 1, 2, 3 }); } 
+9
c # random mocking nsubstitute
source share
4 answers

NSubstitute cannot blink on extension methods according to Sriram's comment, but you can still pass a laughed argument to the extension method.

In this case, the Random class has virtual methods, so we can spoof it directly using the NSubstitute tools and other tools based on a dynamic proxy server. (For NSubstitute in particular, we need to be very careful about mocking classes. Please read the warning in the documentation .)

 public static class RandomExtensions { public static IEnumerable<int> NextInt32s(this System.Random random, int neededValuesNumber, int minInclusive, int maxExclusive) { /* ... */ } } public class RandomExtensionsTests { [Test] public void Select() { const int min = 0, max = 10; var randomizer = Substitute.For<Random>(); randomizer.Next(min, max).Returns(1, 2, 3); var result = randomizer.NextInt32s(3, 0, 10).ToArray(); Assert.AreEqual(new[] {1, 2, 3}, result); } } 
+3
source share

Yes, you can scoff at creating an interface like IRandom , and extend the interface instead of the actual implementation. Then you should be able to trick the interface into your test class.

 public interface IRandom { } public class Random : IRandom { } public static class RandomExtensions { public static string NextInt32s( this IRandom random, int neededValuesNumber, int minInclusive, int maxExclusive) { } } 

In your test class add:

 IRandom randomizer = Substitute.For<IRandom>(); var result = randomizer.NextInt32s(3,0,10); 

In this process, you are simply mocking the interface, not the actual class.

0
source share

As a complement to the other answers, here's how I got around it.

Imagine that there is an IDoStuff interface and there is a library that extends IDoStuff . You have a MyClass class that implements IDoStuff , and somewhere someone uses an extension method for an interface. It looks like this;

 using System; interface IDoStuff { string SayHello(); } class MyClass : IDoStuff { public string SayHello() { return "Hello"; } } // somewhere someone wrote an extension method for IDoStuff static class DoStuffExtensions { static string SayHelloToBob(this IDoStuff other) { return other.SayHello() + " Bob"; } } class UserOfIDoStuff { void UseIDoStuff(IDoStuff incoming) { Console.WriteLine(incoming.SayHelloToBob()); } } 

You want to simulate IDoStuff , but you cannot simulate the SayHelloToBob extension method. What you can do is create another interface that implements IDoStuff , but also includes SayHelloToBob .

 interface IDoStuffWithExtensions : IDoStuff { string SayHelloToBob(); } class MyClass : IDoStuffWithExtensions { public string SayHello() { return "Hello"; } // Wrap / internalise the extension method public string SayHelloToBob() { return DoStuffExtensions.SayHelloToBob(this); } } class UserOfIDoStuff { void UseIDoStuff(IDoStuffWithExtensions incoming) { Console.WriteLine(incoming.SayHelloToBob()); } } 

Now you can happily mock IDoStuffWithExtensions .

0
source share

According to the inversion of the SOLID dependency, the inversion determines that the low-level model should not depend on the high-level model, but depends on the abstract type of interface and mocking concept, mainly used for the layout of the interface so that the low-level model is not tested.

-2
source share

All Articles