Learn when static methods can’t be unit tested and how to use wrapper classes and the Moq and xUnit frameworks to unit test them when they can Credit: Thinkstock When building or working in .NET applications you might often use static methods. Methods in C# can be either static or non-static. A non-static method (also known as an instance method) can be invoked on an instance of the class to which it belongs. Static methods don’t need an instance of the class to be invoked — they can be called on the class itself. Although testing a non-static method (at least one that doesn’t call a static method or interact with external dependencies) is straightforward, testing a static method is not an easy task at all. This article talks about how you can overcome this challenge and test static methods in C#. [ Also on InfoWorld: How to refactor God objects in C# ] To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can download Visual Studio 2019 here. Create a .NET Core console application project in Visual Studio First off, let’s create a .NET Core Console Application project in Visual Studio. Assuming Visual Studio 2019 is installed in your system, follow the steps outlined below to create a new .NET Core console application project in Visual Studio. Launch the Visual Studio IDE. Click on “Create new project.” In the “Create new project” window, select “Console App (.NET Core)” from the list of templates displayed. Click Next. In the “Configure your new project” window shown next, specify the name and location for the new project. Click Create. This will create a new .NET Core console application project in Visual Studio 2019. In similar fashion, create two more projects – a class library and a unit test (xUnit test) project. We’ll use these three projects to illustrate unit testing of static methods in the subsequent sections of this article. When a static method can and can’t be unit tested Unit testing a static method is no different than unit testing a non-static method. Static methods are not untestable in themselves. A static method that holds no state or doesn’t change state can be unit tested. As long as the method and its dependencies are idempotent, the method can be unit tested. The problems arise when the static method calls other methods or when the object being tested calls the static method. On the other hand, if the object being tested calls an instance method, then you can unit test it easily. A static method cannot be unit tested if any of the following holds true: The static method interacts with external dependencies such as a database, file system, network, or external API. The static method holds state information, i.e., if it caches data into a static object of the class. Consider the following code snippet that shows two classes, namely ProductBL and Logger. While ProductBL is a non-static class, Logger is a static class. Note that the Write method of the Logger class has been called from the LogMessage method of the ProductBL class. public class ProductBL { public void LogMessage(string message) { Logger.Write(message); } } public class Logger { public static void Write(string message) { //Write your code here to log data } } Assume that the Write method of the Logger class connects to a database and then writes the data to a database table. The name of the database and its table where the data should be written might be pre-configured in the appsettings.json file. How can you now write unit tests for the ProductBL method? Note that static methods cannot be mocked easily. As an example, if you have two classes named A and B and class A uses a static member of class B, you wouldn’t be able to unit test class A in isolation. Three ways to unit test static methods You can use Moq to mock non-static methods but it cannot be used to mock static methods. Although static methods cannot be mocked easily, there are a few ways to mock static methods. You can take advantage of the Moles or Fakes framework from Microsoft to mock static method calls. (The Fakes framework was included in Visual Studio 2012 as the successor to Moles – it is the next generation of Moles and Stubs.) Another way to mock static method calls is by using delegates. There is yet another way to mock static method calls in an application – by using wrapper classes and dependency injection. IMHO this last option is the best solution to the problem. All you need to do is wrap the static method call inside an instance method and then use dependency injection to inject an instance of the wrapper class to the class under test. Create a wrapper class in C# The following code snippet illustrates the LogWrapper class that implements the IWrapper interface and wraps a call to the Logger.Write() method inside an instance method called LogData. public class LogWrapper : IWrapper { string _message = null; public LogWrapper(string message) { _message = message; } public void LogData(string message) { _message = message; Logger.Write(_message); } } The following code snippet shows the IWrapper interface. It contains the declaration of the LogData method. public interface IWrapper { void LogData(string message); } The ProductBL class uses dependency injection (constructor injection) to inject an instance of the LogWrapper class as shown in the code listing given below. public class ProductBL { readonly IWrapper _wrapper; static string _message = null; public ProductBL(IWrapper wrapper) { _wrapper = wrapper; } public void LogMessage(string message) { _message = message; _wrapper.LogData(_message); } } The LogMessage method of the ProductBL class calls the LogData method on the instance of the LogWrapper class that has been injected earlier. Use xUnit and Moq to create a unit test method in C# Open the file UnitTest1.cs and rename the UnitTest1 class to UnitTestForStaticMethodsDemo. The UnitTest1.cs files would automatically be renamed to UnitTestForStaticMethodsDemo.cs. We’ll now take advantage of the Moq framework to set up, test, and verify mocks. The following code snippet illustrates how you can use the Moq framework to unit test methods in C#. var mock = new Mock<IWrapper>(); mock.Setup(x => x.LogData(It.IsAny<string>())); new ProductBL(mock.Object).LogMessage("Hello World!"); mock.VerifyAll(); When you execute the test, here’s how the output should look in the Test Explorer Window. IDG Figure 1. Moq unit test output. The complete code listing of the test class is given below for your reference. public class UnitTestForStaticMethodsDemo { [Fact] public void StaticMethodTest() { var mock = new Mock<IWrapper>(); mock.Setup(x => x.LogData(It.IsAny<string>())); new ProductBL(mock.Object).LogMessage("Hello World!"); mock.VerifyAll(); } } Unit testing is a process that tests units of code in an application to check if the actual results from your unit test match the desired results. If used judiciously unit testing can help prevent bugs in the development phase of a project. Static methods can pose a number of problems when you attempt to unit test them using mocks. If your application requires you to mock a static method, you should consider that a design smell – i.e., an indicator of a bad design. I’ll discuss mocks, fakes, and stubs in more detail in a future article here. How to do more in C#: How to refactor God objects in C# How to use ValueTask in C# How to use immutability in C How to use const, readonly, and static in C# How to use data annotations in C# How to work with GUIDs in C# 8 When to use an abstract class vs. interface in C# How to work with AutoMapper in C# How to use lambda expressions in C# How to work with Action, Func, and Predicate delegates in C# How to work with delegates in C# How to implement a simple logger in C# How to work with attributes in C# How to work with log4net in C# How to implement the repository design pattern in C# How to work with reflection in C# How to work with filesystemwatcher in C# How to perform lazy initialization in C# How to work with MSMQ in C# How to work with extension methods in C# How to us lambda expressions in C# When to use the volatile keyword in C# How to use the yield keyword in C# How to implement polymorphism in C# How to build your own task scheduler in C# How to work with RabbitMQ in C# How to work with a tuple in C# Exploring virtual and abstract methods in C# How to use the Dapper ORM in C# How to use the flyweight design pattern in C# Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos