c# Mock interface vs mock class - c#

I'm new to the moq framework in .net.
From my research online, it seems like there are 2 ways to make use of this framework. Either mock the interface or mock a concrete class. Seems like when mocking concrete class, only virtual method can be mocked. In my case, I just want to mock a couple method of a class which implements an interface.
For example, if we have the following:
public interface Ifoo
{
int Bar();
}
public class Foo : Ifoo
{
public virtual int Bar()
{
return 0;
}
}
public class Client
{
public Client(Ifoo foo)
{
var temp = foo.Bar();
}
}
Now if I need to unit test Client, I need to pass a mocked Ifoo object in the ctor. In this case, should I do:
var mock = new Mock<Ifoo>();
or
var mock = new Mock<Foo>();
Does it make a difference in my case? What's the pros and cons of mocking interface vs mocking class? To me, mocking interface is always a better solution since mocking a class can only give the mock of the virtual method.

Here are some points to consider:
Your client consumes IFoo, so that's what you should mock.
If your client consumes a concrete class, you should think about refactoring your client to consume the interface or abstract class instead to comply with SOLID principles.
If your client consumes a mock of Foo during your test instead of the interface and it relies on some of the non-mocked behavior in that test, you're not really writing a unit test since you're testing the behavior of more than one unit.
If your client doesn't consume any non-mocked behavior during the test then you might as well just pass a mock of the interface anyway.
tldr: Classes should consume interfaces or abstract classes rather than concrete classes. Tests should mock interfaces or abstract classes rather than concrete classes.

Related

C# unit testing using mocks without interfaces

In order to properly unit test some of my classes I need to mock the class objects being used by the main class being tested. This is a simple process if all the objects being used implements the interface and I only need to use the methods form that interface. However, and here is the problem:
Interfaces are a contract on what other developers should expect in that class. Therefore all interface methods, properties etc. are public. Any good code should also have good encapsulation. Therefore I don't want to make all methods in my class public and hence don't declare it in the interface. And as a result I can not mock and setup these internal method that is used in my main class.
Other options I looked into was using an abstract class that can have different access modifiers and I can have the correct methods in it be internal or private etc. But since I want the class being mocked to be available is a public property of interface type for other developers to use, I need it be an interface, but now its not compatible anymore since my main class cant call the internal method anymore as its defined as an interface. Catch 22. (In case you were wondering, using virtual for methods will have the same problem as using an abstract class).
I have searched for similar questions regarding C# mocking and did not find the same problem I have. And please don't be philosophical on "C# isn't good language for testing" or such stuff. That's not an answer.
Any ideas?
I added this code example to make it easier to see the problem described above.
[assembly: InternalsVisibleTo("MyService.Tests")]
public interface IMyService
{
MethodABC()
...
}
public class MyService : IMyService
{
public void MethodABC()
{
...
}
internal void Initialize()
{
...
}
...
}
public sealed partial class MyMain
{
public IMyService Service { get; private set; }
private MyService _service;
...
private void SomeMethod()
{
// This method is in interface and can be used outside the project when this assembly is referenced
_service.MethodABC()
...
// This method is and internal method inside the class not to be seen or used outside the project.
// 1) When running this method through unit test that mocked the IMyService will fail here since initialize don't exist which is correct.
// 2) Mocking the MyService will require "virtual" to be added to all methods used and don't provide a interface/template for a developers if
// they want to swap the service out.
// 3) Changing the interface to abstract class and mocking that allows for making this an internal method and also set it up in mock to do
// something for unit test and provides contract other developers can implement and pass in to use a different service, but requires
// "override" for all methods to be used from "outside" this assembly. This is best solution but require changes to code for sole purpose
// of testing which is an anti-pattern.
_service.Initialize()
...
}
}
// Unit test method in test project
[TestClass]
public class MyMainTests
{
private Mock<IMyService> _myServiceMock = new Mock<IMyService>();
[TestMethod]
public void MyMain_Test_SomeMethod()
{
...
SomeMethod()
...
}
}
Interface testing doesn't make sense. Interface doesn't say anything about "what it should do". When I need test something with interface, I make MockClass in my NUnit testing class. This class works only for few tests, and it is internal. If you have same namespaces for your tested class and your tests, there should be internal enough. So it is not public. But still you cannot test any private methods.
Sometimes it is annoying, but I cannot have nice code in my tests. But it is not strange.
I get the point of testing only public methods and properties but sometimes this limitation just makes no sense as well as using interfaces just to support unit tests.
My workaround is to inherit the class I am testing, add public access methods and then call protected base class members from it.
One option to consider is to specify the internal actions on an internal interface that you can then use to mock those actions. Given your example, you could add:
internal interface IInitialize
{
void Initialize();
}
And then implement this in your class alongside your public interface:
public class MyService : IMyService, IInitialize
And then your consuming class can use the interface as needed:
public sealed partial class MyMain
{
public MyMain(IMyService myService)
{
Service = myService;
}
public IMyService Service { get; }
public void SomeMethod()
{
(Service as IInitialize)?.Initialize();
Service.MethodABC();
}
}
Now in the unit test you can utilize the As<TInterface>() method in Moq to handle the multiple interfaces (read the docs):
[Fact]
public void Test1()
{
Mock<IMyService> myServiceMock = new Mock<IMyService>();
Mock<IInitialize> myServiceInitializeMock = myServiceMock.As<IInitialize>();
//myServiceMock.Setup(s => s.MethodABC()).Whatever
//myServiceInitializeMock.Setup(s => s.Initialize()).Whatever
MyMain myMain = new MyMain(myServiceMock.Object);
myMain.SomeMethod();
myServiceMock.Verify(s => s.MethodABC(), Times.Once);
myServiceInitializeMock.Verify(s => s.Initialize(), Times.Once);
}
Note the following remark on As<TInterface>():
This method can only be called before the first use of the mock
Moq.Mock`1.Object property, at which point the runtime type has
already been generated and no more interfaces can be added to it.
Also note that the use of As<TInterface>() also requires the following attribute to allow the mock proxy access to implement the internal interface:
[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]
Unfortunately there don't seem to be a clean way of doing this. In order to create a mock using Moq, it needs to be either an interface, abstract class or virtual methods.
Interfaces cant have encapsulation lower than public. Using a internal interface will still force you to create "Public" methods.
Virtual methods allow access modifiers but do not provide an injectable object with a contract to be used by Moq other developers using the main class.
The ideal solution would not require code changes just for the purpose of making it unit testable. This unfortunately don't seem to be possible.
Which brings me to an abstract class that can provide a template (semi interface) that can be handled like an interface but will require "override" for all contract methods but at least will allow correct access modifiers for methods.
This still goes against clean code as I will need to add code to all my methods for the sole purpose of making it unit testable.
This is something Microsoft can look into for new .Net C# features. I will check if they have a feature request for this already.

Why mocking a Repository requires a virtual function and mocking IRepository overrides the existing function?

I am doing unit testing using NUnit and Moq framework. When I try to mock the IRepository using mockRepo.Setup(x=>x.GetStr(It.IsAny)()).Returns(str) then the method which is to be tested gets overridden inside Repository class and the build fails. But instead mocking the IRepository if I mock the Repository making the method which is to be tested as virtual then the data is getting mocked and the test runs.
Any kind of mocking relies on members to be overridable. Your mocking-framework will create some class that either implements your interface or overrides your class. So what the framework creates is similar to the following:
class WeirdClassName : IRepository
{
string GetString(object o) => "SomeString";
}
or if your member would be a class-member this:
class WeirdClassName : Repository
{
string override GetString(object o) => "SomeString";
}
Interface-members are implictely overridable, as they literally do not provide any own logic. You can allways provide your own implementation for it. Class-members are only overridable, if they are virtual.
In your case there seems to be some difference in the test depending on if you mock the interface or the class. That probably indicates your test depends on some internals of the class - e.g. some initialization on the repo. You should either mock that also, or decouple your test from that dependency.

Mocking Multiple Implementations of the interface used as IEnumerable in DI

Using ASP.NET core Dependency injection to inject multiple implementations of an Interface.
This is how my code looks:
public factory(IEnumerable<ISomeInterface> interfaceImplList){}
public class Impl1:ISomeInterface(){}
public class Impl2:ISomeInterface(){}
public class Impl3:ISomeInterface(){}
public class Impl4:ISomeInterface(){}
All the above implementations are injected into the factory and factory will return some implementation based on some configs (Not related to the question)
Now I want to mock this factory using moq. Is there a way to do that, or should I create all the mocked implementations of above classes and them put them in a IEnumerable and pass?
Also another question, is it even a good unit testing practice to create a factory to return mocked instance or should I directly unit test the individual implementations?

How do I mock a class without an interface?

I am working on .NET 4.0 using C# in Windows 7.
I want to test the communication between some methods using mock. The only problem is that I want to do it without implementing an interface. Is that possible?
I just read a lot of topics and some tutorials about mock objects, but all of them used to mock interfaces, and not the classes. I tried to use Rhino and Moq frameworks.
Simply mark any method you need to fake as virtual (and not private). Then you will be able to create a fake that can override the method.
If you use new Mock<Type> and you don't have a parameterless constructor then you can pass the parameters as the arguments of the above call as it takes a type of param Objects
Most mocking frameworks (Moq and RhinoMocks included) generate proxy classes as a substitute for your mocked class, and override the virtual methods with behavior that you define. Because of this, you can only mock interfaces, or virtual methods on concrete or abstract classes. Additionally, if you're mocking a concrete class, you almost always need to provide a parameterless constructor so that the mocking framework knows how to instantiate the class.
Why the aversion to creating interfaces in your code?
With MoQ, you can mock concrete classes:
var mocked = new Mock<MyConcreteClass>();
but this allows you to override virtual code (methods and properties).
I think it's better to create an interface for that class. And create a unit test using interface.
If it you don't have access to that class, you can create an adapter for that class.
For example:
public class RealClass
{
int DoSomething(string input)
{
// real implementation here
}
}
public interface IRealClassAdapter
{
int DoSomething(string input);
}
public class RealClassAdapter : IRealClassAdapter
{
readonly RealClass _realClass;
public RealClassAdapter() => _realClass = new RealClass();
int DoSomething(string input) => _realClass.DoSomething(input);
}
This way, you can easily create mock for your class using IRealClassAdapter.
Hope it works.
If you cannot change the class under test, then the only option I can suggest is using MS Fakes https://msdn.microsoft.com/en-us/library/hh549175.aspx.
However, MS Fakes works only in a few editions of Visual Studio.
The standard mocking frameworks are creating proxy classes. This is the reason why they are technically limited to interfaces and virtual methods.
If you want to mock 'normal' methods as well, you need a tool that works with instrumentation instead of proxy generation. E.g. MS Moles and Typemock can do that. But the former has a horrible 'API', and the latter is commercial.
If worse comes to worse, you can create an interface and adapter pair.
You would change all uses of ConcreteClass to use the interface instead, and always pass the adapter instead of the concrete class in production code.
The adapter implements the interface, so the mock can also implement the interface.
It's more scaffolding than just making a method virtual or just adding an interface, but if you don't have access to the source for the concrete class it can get you out of a bind.
It is a bit old question but nevertheless. There are powerful mocking frameworks these days that are capable of mocking concrete classes like JustMock and Typemock.
I faced something like that in one of the old and legacy projects that i worked in that not contains any interfaces or best practice and also it's too hard to enforce them build things again or refactoring the code due to the maturity of the project business, So in my UnitTest project i used to create a Wrapper over the classes that I want to mock and that wrapper implement interface which contains all my needed methods that I want to setup and work with, Now I can mock the wrapper instead of the real class.
For Example:
Service you want to test which not contains virtual methods or implement interface
public class ServiceA{
public void A(){}
public String B(){}
}
Wrapper to moq
public class ServiceAWrapper : IServiceAWrapper{
public void A(){}
public String B(){}
}
The Wrapper Interface
public interface IServiceAWrapper{
void A();
String B();
}
In the unit test you can now mock the wrapper:
public void A_Run_ChangeStateOfX()
{
var moq = new Mock<IServiceAWrapper>();
moq.Setup(...);
}
This might be not the best practice, but if your project rules force you in this way, do it. Also Put all your Wrappers inside your Unit Test project or Helper project specified only for the unit tests in order to not overload the project with unneeded wrappers or adaptors.
Update:
This answer from more than a year but in this year i faced a lot of similar scenarios with different solutions.
For example it's so easy to use Microsoft Fake Framework to create mocks, fakes and stubs and even test private and protected methods without any interfaces.
You can read: https://learn.microsoft.com/en-us/visualstudio/test/isolating-code-under-test-with-microsoft-fakes?view=vs-2017

Unit testing interface implementations, how to do it?

How to test the behavior of the implementations of interface methods in (abstract) classes without having to copy the tests to each class?
I have (abstract) classes that implement multiple interfaces. I know how each interface should behave, and I define this in test methods so that I don't have to manually repeat these tests for each and every implementation of an interface.
I could create for each interface an abstract class with the tests, and have an abstract method CreateSUT() that creates a new instance of the concrete class. But then I'd have to create a new class with the same CreateSUT() implementation for each interface a class implements, as C# does not support multiple inheritance. Is there a better way to do this?
Also note that I also want to test interfaces implemented in abstract classes that have several non-abstract subclasses, complicating the matter slightly.
This question is not about whether I should unit test my interface implementations. Opinions differ and I've decided to do it because I know how the interface implementations are expected to behave (never returning a null value, returning a read-only collection, etc) and putting these tests together makes it much easier for me to test their implementations, however many there may be.
Well, I didn't understand why you need this, but you can write static helper class with tests for your interface. E.g.
public static class IFooTests
{
public static void ShouldDoSomething(this IFoo foo)
{
// Assert something
}
}
Later for every object that implements IFoo interface you can quickly create test methods:
[Test]
public void ShouldDoSomething()
{
Bar bar = new Bar(); // create and setup your concrete object
bar.ShouldDoSomething(); // call interface test extension
}
You could create a list to hold instances of all concrete implementations of your interface, then go through each element in that list and assert the invariant in your test.
Depending on your test framework, there should be a way to get actionable feedback when the test fails.
A quick search found me this for nUnit: http://www.nunit.org/index.php?p=testCaseSource&r=2.5.9
You can mock the abstract class with moq or make a interface that implements all your interfaces and then have your abstract class implement your newly created interface then mock the new interface.

Categories

Resources