Mock a concrete class - c#

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.

Related

What is the best approach to test abstract classes with parameterized constructors using NUnit and C#?

I am looking for the best way to test an abstract class with constructor parameters. It is important to me that I can also include members that are marked as protected. Here is what I came up with. Let's take the following class as an example:
public abstract class MyAbstractClass {
public MyAbstractClass(string someParam) { ... }
protected int MethodToTest(int param1, int param2) { ... }
}
One possibility would be to derive the TestFixture directly from the abstract class and thus gain access to the members that are marked as protected. But what I rather don't like about it is that I have to pass the constructor parameter in the TestFixture attribute. Furthermore, I have introduced a magic string in addition to this (admittedly, I could still put it into a constant).
[TestFixture("constructor param here")]
public class MyTestFixture : MyAbstractClass {
public MyTestFixture(string someParam) { ... }
[Test]
public void ConstructorTest() {
Assert.Throws<ArgumentNullException>(() => _ = new MyTestFixture(null!));
}
[Test]
public void MethodTest() {
Assert.That(this.MethodToTest(1, 2), Is.EqualTo(3));
}
}
Another way might be to simply build a class (in the unit test project) around the abstract class and pass the protected member through. Somehow that doesn't seem very practical to me either. Above all, it bloats the file containing the test terribly as soon as the classes get bigger.
[TestFixture]
public class MyTestFixture {
private class MyAbstractClassWrapper : MyAbstractClass {
public MyAbstractClassWrapper(string someParam) : base(someParam) { }
public new int MethodToTest(int param1, int param2) => base.MethodToTest(param1, param2);
}
[Test]
public void ConstructorTest() {
Assert.Throws<ArgumentNullException>(() => _ = new MyAbstractClassWrapper(null!));
}
[Test]
public void MethodTest() {
MyAbstractClassWrapper sut = new("constructor param");
Assert.That(sut.MethodToTest(1, 2), Is.EqualTo(3));
}
}
What do you guys think? Are there any better solutions or do I have to settle with my approaches above?

How can you mock the methods from a class if you have no control over the class?

I'm using Xunit and Moq for unit testing. So far I was able to succesfully mock and test methods from interfaces.
But how am I supposed to mock and test the methods of a class that I have no control over. The class has no interface and the methods are not virtual.
I looked into Type Mock Isolator, but I could not make that work, and also that is not a feasible solution because it's paid and only has a 14 day trial, and I need to do this long term.
What are my options?
Create a wrapper for the dependency. You don't need to test the implementation of code you didn't write. Mock the dependency wrapper with the anticipated or hypothetical outputs.
public sealed class SomeBadDependency
{
public int CalculateSuperSecretValue(int inputX, int inputY)
{
return Math.Max(inputX, inputY);
}
}
public interface IDependencyWrapper
{
int CalculateSuperSecretValue(int inputX, int inputY);
}
public sealed class DependencyWrapper : IDependencyWrapper
{
private readonly SomeBadDependency _someBadDependency;
public DependencyWrapper(SomeBadDependency someBadDependency)
{
_someBadDependency = someBadDependency;
}
public int CalculateSuperSecretValue(int inputX, int inputY)
{
return _someBadDependency.CalculateSuperSecretValue(inputX, inputY);
}
}
public sealed class YourCode
{
private readonly IDependencyWrapper _dependencyWrapper;
public YourCode(IDependencyWrapper dependencyWrapper)
{
_dependencyWrapper = dependencyWrapper;
}
public decimal CalculateYourValue(decimal inputX, decimal inputY)
{
return _dependencyWrapper.CalculateSuperSecretValue((int) inputX, (int) inputY);
}
}

Mock call to protected method of base abstract class from derived class public method using Microsoft.fakes

I am trying to write unit test for the code shown below using Microsoft.Fakes.
As new to Microsoft.Fakes i am facing difficulty in mocking the call to abstract base class protected functional method
My base class:
public abstract class MyAbstractBaseClass
{
protected virtual int MyFunctionalBaseClassMethod(int parameter1)
{
return (parameter1 * parameter1);
}
}
My child class:
public class MyChildClass : MyAbstractBaseClass
{
public int GetSquare(int parameter1) //(target method for unit test)
{
return MyFunctionalBaseClassMethod(parameter1); //(target method to mock using Fakes)
}
}
I tried following unit test code for mocking, but didn't work:
var square = 10;
var stubMyAbstractBaseClass = new Fakes.StubMyAbstractBase()
{
MyFunctionalBaseClassMethod = (a) => { return square; }
};
Note: My abstract base class protected method performs complex operations so i need to mock it. The above code is just a sample.
Any pointers would be appreciated!
You need to stub out MyChildClass instead of the abstract class. This worked for me.
[TestMethod]
public void CheckAbstractClassStub()
{
var myChild = new StubMyChildClass()
{
MyFunctionalBaseClassMethodInt32 = (num) => { return 49; }
};
int result = myChild.GetSquare(5);
Assert.AreEqual(result, 49);
}
Edit: Yes, it is protected. As I mentioned above, you need to stub out the protected method in the derived class, MyChildClass. You have stubbed out the abstract class, there's no instance there and it will not get called. If you want to do it for all instances, you may be able to use Shims, but you're just making it more difficult at that point.
Here's my base class and subclass so you can compare.
public abstract class MyAbstractBaseClass
{
protected virtual int MyFunctionalBaseClassMethod(int parameter1)
{
return (parameter1 * parameter1);
}
}
public class MyChildClass : MyAbstractBaseClass
{
public int GetSquare(int parameter1) //(target method for unit test)
{
return MyFunctionalBaseClassMethod(parameter1); //(target method to mock using Fakes)
}
}
Here's a screen shot of the code stopped at a debug point

NSubstitute mock extension method

I want to do 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 });
}
NSubstitute can not mock extension methods as per Sriram's comment, but you can still pass a mocked argument to an extension method.
In this case, the Random class has virtual methods, so we can mock that directly with NSubstitute and other DynamicProxy-based mocking tools. (For NSubstitute in particular we need to be very careful 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);
}
}
Yes you can mock if you create an interface such as IRandom and extend the interface instead of the actual implementation. Then you should be able mock the interface in 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);
By this process you are just mocking the interface not the actual class.
As an extension to other answers, here is how I got round it.
Imagine there is an interface IDoStuff and there is a library that extends IDoStuff. You have a class MyClass that implements IDoStuff and somewhere someone uses the extension method against the 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 mock IDoStuff but you cannot mock the extension method SayHelloToBob. What you can do is to 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.
According to SOLID principle dependence inversion defines that lower level model should not be depended high level model but depended on abstract like interface and mocking concept is mainly used to mock interface so that low level model is not tested.

c# constructor vs initialize

Doing TDD and want to isolate the method under test: Direct();
However, when the test creates MyClass, SomeClass.SetupStuff(); blows up (NotImplementedException). So, modified the IMyClass interface to have a Configure(); method that can be called after MyClass construction to avoid the exception.
Question: Is this an accepted way of handling this scenario or is there some basic OOP principal that this breaks?
public class MyClass : IMyClass
{
public MyClass()
{
// class with static method that sets stuff up
SomeClass.SetupStuff();
}
public void IMyClass.Direct()
{
// want to test this
}
}
vs
public class MyClass : IMyClass
{
public MyClass()
{
}
public void IMyClass.Direct()
{
// want to test this
}
//
public void IMyClass.Configure()
{
// class with static method that sets stuff up
SomeClass.SetupStuff();
}
}
One way to avoid such problems is to use dependency injection
public class MyClass : IMyClass
{
public MyClass(ISomeClass someClass)
{
someClass.SetupStuff();
}
public void IMyClass.Direct()
{
// want to test this
}
}
By decoupling your class from SomeClass, you are free to provide a mock implementation of ISomeClass during test and can provide a full implementation at runtime.

Categories