0

I'm trying to mock a static class and static method in C# using NSubstitute. I obviously don't want to Generate an excel file for every unit test. So I definitely want to mock. But since this is a static class, I'm unable to mock as this is a static class.

public static class FileGenerator 
{
    public static async Task GenerateExcelFile(string filename, IEnumerable<T> content) 
    {
        .....
    }
}

var mockobj =  Substitute.For<FileGenerator>(); // Returns error

Any hint?

croxy
  • 4,082
  • 9
  • 28
  • 46
VKh
  • 151
  • 2
  • 10
  • _I'm unable to mock as this is a static class_ - this is an answer - don't use static. – Fabio Feb 28 '20 at 22:57
  • NSubstitute can not mock static classes (see [How NSub Works](https://nsubstitute.github.io/help/how-nsub-works/); it needs to be able to subclass or implement an interface). @Christopher's answer has some good options to consider. – David Tchepak Mar 01 '20 at 22:38

2 Answers2

0

It is a good idea to use static only very sparringly. It is one of those mechanics that is easily and often missused as a shortcut. But those always end up causing issues down the line.

For constants or runtime constants it is okay to use a static. But do not use it for changing data. Something called FileGenerator? Right there with things you should not be making static.

Instead:

  • create a normal class that needs instantiation
  • create a instance and assign it to a static field

Now you can easily have multiple instance in paralell. You can also extract a interface/abstract class and then create a different implementation. Including a mock implementation.

Christopher
  • 9,634
  • 2
  • 17
  • 31
0

Now you can use source generators to produce interface and its implementation for a static class. For example I do such thing for Clipboard class. The example of my source generator is here: https://github.com/Tum4ik/just-clipboard-manager/blob/main/Tum4ik.SorceGenerators/StaticClassInterfaceAndImplementationGenerator.cs

So, to generate interface and implementation for the Clipboard static class I just need to write this:

[IIForStaticClass(typeof(Clipboard), "ClipboardWrapper")]
internal partial interface IClipboard
{
}