Unit tests for multiple static classes - c#

I have the below pseudo code to explain the code I've to write some unit tests for.
I wanted to create a unittest for ClassA but because it uses ClassB (that is using ClassC) I'm in doubt how to approach it. I'm not sure if the code itself should be structured otherwise or I just don't know how to handle the Testing this the right way.
I should be able to mock ClassB but then I should create a ClassBFactory? But then I've the idea I'm creating everything by Factories just for being able to write Unit Tests.
Public class ClassA
{
public ClassA()
{
}
public object DoSomething(object request)
{
object result = ClassB.GetMeSomething(request.Property);
// .. do other things
return result;
}
}
public static class ClassB
{
public static object GetMeSomething(string param1)
{
string convertedParam = ClassC.Convert(param1);
// ... do other things with convertedParam
return result;
}
}
public static class ClassC
{
public static string Convert(string param)
{
// .. Some logic to do a external API request
string result = ExternalAPI.Get(param);
return result;
}
}

Related

Can't mock an extension method wtih JustMock [duplicate]

I am writing a test that depends on the results of an extension method but I don't want a future failure of that extension method to ever break this test. Mocking that result seemed the obvious choice but Moq doesn't seem to offer a way to override a static method (a requirement for an extension method). There is a similar idea with Moq.Protected and Moq.Stub, but they don't seem to offer anything for this scenario. Am I missing something or should I be going about this a different way?
Here is a trivial example that fails with the usual "Invalid expectation on a non-overridable member". This is a bad example of needing to mock an extension method, but it should do.
public class SomeType {
int Id { get; set; }
}
var ListMock = new Mock<List<SomeType>>();
ListMock.Expect(l => l.FirstOrDefault(st => st.Id == 5))
.Returns(new SomeType { Id = 5 });
As for any TypeMock junkies that might suggest I use Isolator instead: I appreciate the effort since it looks like TypeMock could do the job blindfolded and inebriated, but our budget isn't increasing any time soon.
Extension methods are just static methods in disguise. Mocking frameworks like Moq or Rhinomocks can only create mock instances of objects, this means mocking static methods is not possible.
If you can change the extension methods code then you can code it like this to be able to test:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
public static class MyExtensions
{
public static IMyImplementation Implementation = new MyImplementation();
public static string MyMethod(this object obj)
{
return Implementation.MyMethod(obj);
}
}
public interface IMyImplementation
{
string MyMethod(object obj);
}
public class MyImplementation : IMyImplementation
{
public string MyMethod(object obj)
{
return "Hello World!";
}
}
So the extention methods are only a wrapper around the implementation interface.
(You could use just the implementation class without extension methods which are sort of syntactic sugar.)
And you can mock the implementation interface and set it as implementation for the extensions class.
public class MyClassUsingExtensions
{
public string ReturnStringForObject(object obj)
{
return obj.MyMethod();
}
}
[TestClass]
public class MyTests
{
[TestMethod]
public void MyTest()
{
// Given:
//-------
var mockMyImplementation = new Mock<IMyImplementation>();
MyExtensions.Implementation = mockMyImplementation.Object;
var myClassUsingExtensions = new MyClassUsingExtensions();
// When:
//-------
var myObject = new Object();
myClassUsingExtensions.ReturnStringForObject(myObject);
//Then:
//-------
// This would fail because you cannot test for the extension method
//mockMyImplementation.Verify(m => m.MyMethod());
// This is success because you test for the mocked implementation interface
mockMyImplementation.Verify(m => m.MyMethod(myObject));
}
}
I know this question hasn't been active for about a year but Microsoft released a framework to handle exactly this called Moles.
Here are a few tutorials as well:
DimeCasts.net
Nikolai Tillman's Tutorial
I created a wrapper class for the extension methods that I needed to mock.
public static class MyExtensions
{
public static string MyExtension<T>(this T obj)
{
return "Hello World!";
}
}
public interface IExtensionMethodsWrapper
{
string MyExtension<T>(T myObj);
}
public class ExtensionMethodsWrapper : IExtensionMethodsWrapper
{
public string MyExtension<T>(T myObj)
{
return myObj.MyExtension();
}
}
Then you can mock the wrapper methods in your tests and code with your IOC container.
For extension methods I normally use the following approach:
public static class MyExtensions
{
public static Func<int,int, int> _doSumm = (x, y) => x + y;
public static int Summ(this int x, int y)
{
return _doSumm(x, y);
}
}
It allows to inject _doSumm fairly easy.
Best thing you can do is to provide a custom implementation for the type that has the extension method, e.g:
[Fact]
public class Tests
{
public void ShouldRunOk()
{
var service = new MyService(new FakeWebHostEnvironment());
// Service.DoStuff() internally calls the SomeExtensionFunction() on IWebHostEnvironment
// Here it works just fine as we provide a custom implementation of that interface
service.DoStuff().Should().NotBeNull();
}
}
public class FakeWebHostEnvironment : IWebHostEnvironment
{
/* IWebHostEnvironment implementation */
public bool SomeExtensionFunction()
{
return false;
}
}

Mock a concrete class

I know that it is not possible to Mock a concrete class but only interfacecs and abstract classes.
Is there any way or any pattern to skirt this?
For example I have the following classes that do not implement any interface. I don't want to create a new instance of C since it will take lot of time in my unit test, how can I mock it and do unit test on Foo()?
public class A
{
public virtual void Foo(){}
}
public class C:A
{
public C()
{
// construction takes lot of time
}
public override void Foo()
{
}
}
Thanks
Disclaimer I work at Typemock.
I know that it is not possible to Mock a concrete class but only
interfaces and abstract classes
With Typemock Isolator you can mock everything, from abstract classes and interfaces to sealed and static classes.
I changed your example a little:
public class A
{
public virtual int Foo() { return 0; }
}
public class C : A
{
public C()
{
// construction takes lot of time
}
private int Bar()
{
return 3;
}
public override int Foo()
{
return Bar() + 1;
}
}
[TestClass]
public class Collections
{
[TestMethod]
public void FakingWithIsolatorExample()
{
var fakeC = Isolate.Fake.Instance<C>();
Isolate.WhenCalled(() => fakeC.Foo()).CallOriginal();
Isolate.NonPublic.WhenCalled(fakeC, "Bar").WillReturn(10);
int result = fakeC.Foo();
Assert.AreEqual(11, result);
}
}
Comments:
The ctor of C was ignored.
The real implementation of Foo was called and tested
A return value was assigned to private method of C.
No changes in your code and additional levels of indirection were needed.

How to mock a private static inner class?

I'd like to ask a question which bother me a lot...
How can I mock the return value of MyPublicStaticMethod_C?? MyPrivateStaticClass_B is really private and static
public static partial class MyPublicStaticClass_A
{
private static partial class MyPrivateStaticClass_B
{
public static int MyPublicStaticMethod_C(string para)
{
//...
}
//...
}
}
I'm going to be slightly unhelpful here and say that you shouldn't mock that.
When writing tests you should only test your public interface, not your private. The private stuff is implementation specific and your tests shouldn't care about that.
If you have a public method that calls your private method and you feel that you need to mock the private method in order to properly test your class - that is a code smell. You should refactor your code and take in the inner private class as an interface, that way you can mock it.
If you do figure out a way to mock this in its current state, it will most likely not really give you a better tested system - however it will get you brittle tests that are hard to maintain.
You must reference the private type through the reflection API using GetNestedType(). Then you can use the non-public mocking API to arrange the method. Here's a working example:
public static partial class MyPublicStaticClass_A
{
public static int Test(string str)
{
return MyPrivateStaticClass_B.MyPublicStaticMethod_C(str);
}
private static partial class MyPrivateStaticClass_B
{
public static int MyPublicStaticMethod_C(string para)
{
return 1;
}
}
}
[TestMethod]
public void ShouldArrangeInnerPrivateClassMethod()
{
var privateType = typeof(MyPublicStaticClass_A).GetNestedType("MyPrivateStaticClass_B", BindingFlags.NonPublic);
Mock.NonPublic.Arrange<int>(privateType, "MyPublicStaticMethod_C").Returns(5);
var result = MyPublicStaticClass_A.Test(null);
Assert.Equal(5, result);
}
But, yeah, having such code should be a last resort - only if refactoring is impossible or unfeasible.

Static repository... can't use DI, what to do?

I am in a situation where we need to modify what is being returned from the static repository in a 3rd party open-source application (NopCommerce). The problem is that they use static repositories, so I can't merely inherit an interface and DI my own repository. I'm trying to do this without modifying the NopCommerce code-base... any fresh ideas?
Edit: I want NopCommerce to use my repos, rather than have my code use theirs.
You could abstract away their stuff by creating an interface of your own and a class implementation that delegates to NopCommerce. Then have your code use the interface instead of directly accessing NopCommerce's classes. You can modify the output of NopCommerce inside your class before the result is returned to your application.
And as an added bonus you could also mock the interface to do some tests that didn't require the full-blown repository implementations.
Something like this, in code:
public interface IRepository
{
MyItem GetItem(int id);
}
public class MyNopCommerceWrapper : IRepository
{
public MyItem GetItem(int id)
{
// I have no idea what NopCommerce API looks like, so I made this up.
var myItem = NopCommerce.GetItem(id);
ModifyMyItem(myItem);
return myItem;
}
}
We are currently on a really, really tight deadline, and this problem was not forseen. So I am thinking of first starting with a poor man's static interface/poor man's DI like the following (so I don't have to modify the entire solution). Then at a later time, when we are not-so-pressed for time, change over to use an interface and dependency injection and submit a patch to NopCommerce:
// Poor-man's static interface (DI).
public static class OriginalBuiltInStaticClass {
private static IMyNewClass _myNewClass;
public static void Inject(IMyNewClass myNewClass) {
_myNewClass = myNewClass;
A = _myNewClass.A;
B = _myNewClass.B;
C = _myNewClass.C;
}
public static Action A = CopySimpleRenameBuiltInStaticClass.A;
public static Func<int, string> B = CopySimpleRenameBuiltInStaticClass.B;
public static Action C = CopySimpleRenameBuiltInStaticClass.C;
}
// Original vendor class which was copied and renamed.
public static class CopySimpleRenameBuiltInStaticClass {
public static void A() {
Console.WriteLine("OriginalBuiltInStaticClass.A()");
}
public static string B(int id) {
Console.WriteLine("OriginalBuiltInStaticClass.B()");
return id.ToString();
}
public static void C() {
Console.WriteLine("OriginalBuiltInStaticClass.C()");
}
}
// Creating an interface to merge into trunk of NopCommerce (convert static repositories)
public interface IMyNewClass {
void A();
string B(int id);
void C();
}
// Implementation of interface.
public class MyNewClass : IMyNewClass {
public void A() {
Console.WriteLine("MyNewClass.A()");
}
public string B(int id) {
Console.WriteLine("MyNewClass.B()");
return id.ToString();
}
public void C() {
CopySimpleRenameBuiltInStaticClass.C();
}
}
Any thoughts?
Sounds like a job for Facade.

How do I use Moq to mock an extension method?

I am writing a test that depends on the results of an extension method but I don't want a future failure of that extension method to ever break this test. Mocking that result seemed the obvious choice but Moq doesn't seem to offer a way to override a static method (a requirement for an extension method). There is a similar idea with Moq.Protected and Moq.Stub, but they don't seem to offer anything for this scenario. Am I missing something or should I be going about this a different way?
Here is a trivial example that fails with the usual "Invalid expectation on a non-overridable member". This is a bad example of needing to mock an extension method, but it should do.
public class SomeType {
int Id { get; set; }
}
var ListMock = new Mock<List<SomeType>>();
ListMock.Expect(l => l.FirstOrDefault(st => st.Id == 5))
.Returns(new SomeType { Id = 5 });
As for any TypeMock junkies that might suggest I use Isolator instead: I appreciate the effort since it looks like TypeMock could do the job blindfolded and inebriated, but our budget isn't increasing any time soon.
Extension methods are just static methods in disguise. Mocking frameworks like Moq or Rhinomocks can only create mock instances of objects, this means mocking static methods is not possible.
If you can change the extension methods code then you can code it like this to be able to test:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
public static class MyExtensions
{
public static IMyImplementation Implementation = new MyImplementation();
public static string MyMethod(this object obj)
{
return Implementation.MyMethod(obj);
}
}
public interface IMyImplementation
{
string MyMethod(object obj);
}
public class MyImplementation : IMyImplementation
{
public string MyMethod(object obj)
{
return "Hello World!";
}
}
So the extention methods are only a wrapper around the implementation interface.
(You could use just the implementation class without extension methods which are sort of syntactic sugar.)
And you can mock the implementation interface and set it as implementation for the extensions class.
public class MyClassUsingExtensions
{
public string ReturnStringForObject(object obj)
{
return obj.MyMethod();
}
}
[TestClass]
public class MyTests
{
[TestMethod]
public void MyTest()
{
// Given:
//-------
var mockMyImplementation = new Mock<IMyImplementation>();
MyExtensions.Implementation = mockMyImplementation.Object;
var myClassUsingExtensions = new MyClassUsingExtensions();
// When:
//-------
var myObject = new Object();
myClassUsingExtensions.ReturnStringForObject(myObject);
//Then:
//-------
// This would fail because you cannot test for the extension method
//mockMyImplementation.Verify(m => m.MyMethod());
// This is success because you test for the mocked implementation interface
mockMyImplementation.Verify(m => m.MyMethod(myObject));
}
}
I know this question hasn't been active for about a year but Microsoft released a framework to handle exactly this called Moles.
Here are a few tutorials as well:
DimeCasts.net
Nikolai Tillman's Tutorial
I created a wrapper class for the extension methods that I needed to mock.
public static class MyExtensions
{
public static string MyExtension<T>(this T obj)
{
return "Hello World!";
}
}
public interface IExtensionMethodsWrapper
{
string MyExtension<T>(T myObj);
}
public class ExtensionMethodsWrapper : IExtensionMethodsWrapper
{
public string MyExtension<T>(T myObj)
{
return myObj.MyExtension();
}
}
Then you can mock the wrapper methods in your tests and code with your IOC container.
For extension methods I normally use the following approach:
public static class MyExtensions
{
public static Func<int,int, int> _doSumm = (x, y) => x + y;
public static int Summ(this int x, int y)
{
return _doSumm(x, y);
}
}
It allows to inject _doSumm fairly easy.
Best thing you can do is to provide a custom implementation for the type that has the extension method, e.g:
[Fact]
public class Tests
{
public void ShouldRunOk()
{
var service = new MyService(new FakeWebHostEnvironment());
// Service.DoStuff() internally calls the SomeExtensionFunction() on IWebHostEnvironment
// Here it works just fine as we provide a custom implementation of that interface
service.DoStuff().Should().NotBeNull();
}
}
public class FakeWebHostEnvironment : IWebHostEnvironment
{
/* IWebHostEnvironment implementation */
public bool SomeExtensionFunction()
{
return false;
}
}

Categories