Fake object that is created by a method, not a constructor - c#

I am trying to unit test code that uses an API, so I am trying to decouple.
I have created an interface for the "Application" class inside the API, which is sealed.
I then created a class that uses the interface which has one method that returns an "Application" type object.
Here is where I am having trouble, in my unit test I try to create an "Application" object to verify if the return value is correct. However the "Application" class does not have any constructors, nothing public or private(I checked with reflection). The object is created by calling static Application.Connect(AnotherTypeFromAPI arg), which returns an Application object.
How do I return a fake object that I cannot create?
appMock.Connect(arg).Returns("How do I return an Application object here?"));
Or am I going about this the wrong way in regards to unit testing code that relies on an API? The entire API relies on the "Application" type so if I cannot fake it, I am not sure yet how I can stub or mock the other methods I need.
I am using C#, NUnit, NSUbstitute.

This problem can be solved but you're using the wrong pattern. Instead of exposing an instance of the Application via a new interface, you need to create an interface that fully replaces the concrete dependency.
What you have
If I understand your question correctly, you have a sealed Application class that has some methods your program needs to be able to call, and it has no public constructor, only a static factory method. Here is a simple example for discussion, with only one method, SomeMethod().
public sealed class Application
{
//private ctor prevents anyone from using new to create this
private Application()
{
}
//Here's the method we want to mock
public void SomeMethod(string input)
{
//Implementation that needs to be stubbed or mocked away for testing purposes
}
//Static factory method
static public Application GetInstance()
{
return new Application();
}
}
What you tried
What you did might look like this:
interface IApplication
{
Application Application { get; }
}
class ApplicationWrapper : IApplication
{
protected readonly Application _application;
public ApplicationWrapper()
{
_application = Application.GetInstance();
}
public Application Application
{
get { return _application; }
}
}
So that in your main code, you do this:
var a = new ApplicationWrapper();
a.Application.SomeMethod("Real argument");
That approach will never work for unit testing, because you still have a direct dependency on the sealed Application class. You've just moved it. You still need to call Application.SomeMethod(), which is a concrete method; you are supposed to depend only on the interface, not anything concrete.
What would work
In theory, the "right" way to do this is to wrap everything. So instead of exposing Application as a property, you keep it private; instead, you expose wrapped versions of the methods, like this:
public interface IApplication
{
void SomeMethod(string input);
}
public class ApplicationWrapper : IApplication
{
protected readonly Application _application;
public ApplicationWrapper()
{
_application = Application.GetInstance();
}
public void SomeMethod(string input)
{
_application.SomeMethod(input);
}
}
Then you'd call it like this:
var a = new ApplicationWrapper();
a.SomeMethod("Real argument");
Or in a full class with DI, it would look like this:
class ClassUnderTest
{
protected readonly IApplication _application; //Injected
public ClassUnderTest(IApplication application)
{
_application = application; //constructor injection
}
public void MethodUnderTest()
{
_application.SomeMethod("Real argument");
}
}
How to unit test
In your unit test, you can now mock the IApplication with a new class, e.g.
class ApplicationStub : IApplication
{
public string TestResult { get; set; } //Doesn't exist in system under test
public void SomeMethod(string input)
{
this.TestResult = input;
}
}
Notice this class has absolutely no dependency on Application. So you no longer need to call new on it, or call its factory method, at all. For unit testing purposed, you just need to ensure it gets called properly. You can do this by passing in the stub and checking the TestResult afterward:
//Arrange
var stub = new ApplicationStub();
var c = ClassUnderTest(stub);
//Act
c.MethodUnderTest("Test Argument");
//Assert
Assert.AreEqual(stub.TestResult, "Test Argument");
It's a bit more work to write the full wrapper (especially if it has a lot of methods), but you can generate a lot of that code with reflection or with third party tools. And it allows you full unit testing, which is the whole idea behind switching to that IApplication interface to begin with.
TLDR:
Instead of
IApplication wrapper = new ApplicationWrapper();
wrapper.Application.SomeMethod();
you should use
IApplication wrapper = new ApplicationWrapper();
wrapper.SomeMethod();
to remove the dependency on the concrete type.

You don't normally mock or fake static methods such as Application.Connect. Just partition the code under test so that it takes an already created IApplication object.

Related

How do I unit test an adapter class?

Suppose I have the following classes from a third-party library:
public class ThirdPartyType { ... }
public class ThirdPartyFunction
{
public ThirdPartyType DoSomething() { ... }
}
The implementation details are not important, and they are actually outside of my control for this third-party library.
Suppose I write an adapter class for ThirdPartyFunction:
public class Adapter
{
private readonly ThirdPartyFunction f;
public Adapter()
{
f = new ThirdPartyFunction();
}
public string DoSomething()
{
var result = f.DoSomething();
// Convert to a type that my clients can understand
return Convert(result);
}
private string Convert(ThirdPartyType value)
{
// Complex conversion from ThirdPartyType to string
// (how do I test this private method?)
...
}
}
How can I test that my implementation of Convert(ThirdPartyType) is correct? It's only needed by the Adapter class, which is why it's a private method.
I would recommend extracting the code to a seprate class and then testing that class. Although it is only used by this Adapter it shouldn't be the responsibility of the adapter to do the conversion as well (in keeping with the Single Responsibility Principle).
By extracting it out it gives you the ability to test the converter in isolation from the third party code.
If the converter does not require any state you could also make it a static class and then reference it directly in your adapter without the need for registering it with dependency injection.
If you think about it, the adapter doesn't need testing (as it is just a wrapper) but the converter does - so extracting it to another class makes sense to allow it to be tested, even if it does mean another class in the code.
In addition, extracting the converter to a separate class means that if the ThirdPartyType or the format of your string changes then you can make the changes without affecting the Adapter implementation.
If you change your Adapter class to allow the ThirdPartyFunction f to be passed to it, then you can use a mock version of it in your test class. this will allow you to test the Convert function.
I'm not sure of the exact syntax as I am not familiar with the language, but I will give it a try:
public class Adapter
{
private readonly ThirdPartyFunction f;
// pass the function to the constructor when creating the adapter
public Adapter(ThirdPartyFunction inputF)
{
f = inputF;
}
public string DoSomething()
{
var result = f.DoSomething();
// Convert to a type that my clients can understand
return Convert(result);
}
private string Convert(ThirdPartyType value)
{
// Complex conversion from ThirdPartyType to string
// (how do I test this private method?)
...
}
}
In your real implementation, when you create the new Adapter, you can pass it a new ThirdPartyFunction.
In your test implementation, you can pass it a Mocked version of that ThirdPartyFunction which returns a fixed value for testing. Maybe like:
class MockThirdPartyFunction extends ThirdPartyFunction
{
private ThirdPartyType testData;
public MockThirdPartyFunction(ThirdPartyType data)
{
testData = data;
}
override public ThirdPartyType DoSomething()
{
// return a fixed third party type passed in on mock creation
return testData
}
}
You create the test adapter with the mocked value, where you can set the specific ThirdPartyType you want to test. Then in your test when you call DoSomething on the Adapter, you are controlling the input to your Convert function and can see the output and compare accordingly to expected results.

Moq CallBase on mock of interface

Let's assume we have the following setup:
public interface IBase
{
void Foo();
}
public class Base : IBase
{
public virtual void Foo()
{
Console.WriteLine("Called Base.Foo()");
}
}
public interface IChild : IBase
{
void Bar();
}
public class Child : Base, IChild
{
public virtual void Bar()
{
Console.WriteLine("Called Child.Bar()");
}
}
When mocking the Child object everything works fine:
var child = new Mock<Child> { CallBase = true };
child.Object.Bar();
child.Object.Foo();
Output is:
Called Child.Bar()
Called Base.Foo()
But when mocking the IChild interface nothing is printed to the console:
var child = new Mock<IChild> { CallBase = true };
child.Object.Bar();
child.Object.Foo();
Let's assume I can't mock the Child object because there is no parameterless constructor (dependency injection).
I know that I could just do the following:
child.Setup(c => c.Bar()).Callback(() =>
{
// Copy paste bar-method body
});
child.Setup(c => c.Foo()).Callback(() =>
{
// Copy paste foo-method body
});
But that would be very ugly.
Is there a clean solution using Mock<IChild>?
As long as you are mocking the interface, you have no access or information about the real classes which explains why you don't get any output (but I guess you understood that).
Unfortunately if you choose to mock an interface (which by definition have no behavior), the only way to make things happen is to Setup the method the way you did.
Another "dirty" way would be to use method extension to your child and base class if the content of the method is only using public attributes and method.
public static class ChildExtension
{
public static void Bar(this Child child)
{
Console.WriteLine("Called Child.Bar()");
}
}
You are going to the wrong direction
Mock exists to help in unit testing. For example if you want to test the method Save() of a class which uses a wrapper over a DbContext like the following:
interface IRepository
{
void PersistData(object dataToBeSaved);
}
class DataSaver
{
private IRepository _repository;//this object's method PersistData makes a call to a database
public DataSaver(IRepository repository)
{
_repository = repository;
}
public void Save(object dataToBeSaved)
{
_repository.PersistData(dataToBeSaved);
}
}
In this case, in order to test the method Save of the DataSaver you will do a call to it in a unit test, but the problem you will face when doing this is that the method will actually try to save the data using the repository objet. Unless you send a fake repository your unit test will save data every time you run it, and this is not what a unit test should be doing. It should not run a method from a concrete IRepository object, but it should still call it's method.
What you could do in this case to avoid saving of an object is to make another class which implements IRepository only for testing:
class DummyRepository : IRepository
{
public object DataJustSaved { get; set; }
public void PersistData(object dataToBeSaved)
{
DataJustSaved = dataToBeSaved;
}
}
Now in your unit test you will do something like this:
var dummyRepository = new DummyRepository();
var dataSaver = new DataSaver(dummyRepository);
var savedObject = new Object();
var expectedObject = savedObject;
dataSaver.Save(savedObject);//test the save method
var actualObject = dummyRepository.DataJustSaved;
Assert.AreEqual(expectedObject, actualObject);//verify that the data was passed to the PersistData method
Here the Mock helps
It would be quite difficult to make a fake class for each unit test, that is what alternative mock offers:
var dummyRepository = new Mock<IRepository>();
var dataSaver = new DataSaver(dummyRepository.Object);
var savedObject = new Object();
dataSaver.Verify(x => x.PersistData(savedObject), Times.Once());// just make sure the method PersistData was invoked with the expected data and only once.
The reason Mock exists is to make pretty smart dummies for you, to write unit tests without a great impact but which can reveal bugs, and keep the code doing what only it's supposed to do.
In your case, if you really want to call the actual method of the concrete object:
child.Setup(c => c.Bar()).Callback(() =>
{
Console.WriteLine("Called Child.Bar()");
});
Then it means that you should not even try to use the mock to reproduce the exact same implementation of the object you mock. What would be the use of the mock if it is doing the same thing as the actual object?
In this case you should remove the mock and create a concrete Child object, as you do not want to simulate the behavior of a child, you are trying to achieve it using a mock which removes the functionality of the mock itself.
The simple answer is to use the concrete object in the unit test:
var child = new Child();
child.Bar();
child.Foo();

How to override some property in the class under test during unit testing

I have a class that I would like to test with Unit tests. It has some logic to look for some values in the local xml file, and if the value is not found it will read some external source (SqlServer DB). But during Unit testing I don't want this component to interact with Sql Server at all. During unit testing I would like to replace SqlServer implementation of the External source reader to some Noop reader. What is the good approach to achieve that? Important note: I can't define constructor that accepts instance of reader type since it is client facing API and I want to limit what they can do with my classes.
I am currently using few ways in Unit tests:
Use reflection to set value of the private/protected property to my mocked implementation of the reader
Define factory that will create concrete class. Register factory in Unity container & class under test will get factory object from DI container and instantiate reader according to my needs
Subclass class-under-test and set property there.
But none of them seem to be clean enough to me. Are there any better ways to achieve that?
Here is the sample code to demonstrate example of the class-under-the-test:
namespace UnitTestProject1
{
using System.Collections.Generic;
using System.Data.SqlClient;
public class SomeDataReader
{
private Dictionary<string, string> store = new Dictionary<string, string>();
// I need to override what this property does
private readonly IExternalStoreReader ExternalStore = new SqlExternalStoreReader(null, false, new List<string>() {"blah"});
public string Read(string arg1, int arg2, bool arg3)
{
if (!store.ContainsKey(arg1))
{
return ExternalStore.ReadSource().ToString();
}
return null;
}
}
internal interface IExternalStoreReader
{
object ReadSource();
}
// This
internal class SqlExternalStoreReader : IExternalStoreReader
{
public SqlExternalStoreReader(object arg1, bool arg2, List<string> arg3)
{
}
public object ReadSource()
{
using (var db = new SqlConnection("."))
{
return new object();
}
}
}
internal class NoOpExternalStoreReader : IExternalStoreReader
{
public object ReadSource()
{
return null;
}
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var objectToTest = new SomeDataReader();
objectToTest.Read("", -5, false); // This will try to read DB, I don't want that.
}
}
In this case, you can use the InternalsVisibleTo attribute, which exposes all internal members to friend assemblies.
You could start by creating a separate internal constructor overload, which can accept a different instance of IExternalStoreReader:
public class SomeDataReader
{
// publicly visible
public SomeDataReader()
: this(new SqlExternalStoreReader(...))
{ }
// internally visible
internal SomeDataReader(IExternalStoreReader storeReader)
{
ExternalStore = storeReader;
}
...
}
And then allow the unit testing assembly to access internal members by adding the InternalsVisibleTo attribute to your AssemblyInfo.cs:
[assembly: InternalsVisibleTo("YourUnitTestingAssembly")]
If you're really concerned about people trying to access your internal members, you can also use strong naming with the InternalsVisibleTo attribute to ensure no one tries to impersonate your unit testing assembly.
The simple answer is: change your code. Because you have a private readonly field that creates its own value, you cannot change that behaviour without getting really hacky, if at all. So instead, don't do it that way. Change the code to:
public class SomeDataReader
{
private Dictionary<string, string> store = new Dictionary<string, string>();
private readonly IExternalStoreReader externalStore;
public SomeDataReader(IExternalStoreReader externalStore)
{
this.externalStore = externalStore;
}
In other words, inject the IExternalStoreReader instance into the class. That way you can create a noop version for unit tests and the real one for production code.
If you're compiling the complete code yourself, you could create a fake SqlExternalStoreReader with a stubbed implementation inside your unit test project.
This stub implementation allows you to access all fields and forward calls to your mocking framework/unit test

Inject/Mock external dll abstract classes' static methods

I have this situation: An azure cloud service that uses an external DLL and makes API calls. This DLL has an abstract class that has a static method to return a subclass reference I need to use to make the API calls.
Now for testing purposes, we run the cloud service in an emulator and run our unit tests. But we don't want to make that API call to the external system. We need to intercept it somehow. I have spent the better part of yesterday trying to see if I could do some dependency injection (unity) to do this but needless to say, no luck.
The abstract class exposing a static method to get an instance of a subclass to actually make the API call is probably the most restrictive of scenarios.
Below is some decompiled & cleaned up code to show the relevant pieces.
public abstract class EntityManager : System.Object
{
private static object lockObject;
private static Dictionary<System.Type, EntityManager> entityManagers;
private bool isSingleton;
public enum EntityManagerInstanceType : int
{
SingletonInstance = 0,
NewInstance = 1,
}
static EntityManager() { }
protected EntityManager() { }
public static T GetEntityManager<T>(EntityManagerInstanceType instanceType) where T : EntityManager
{
T item;
System.Type type = typeof(T);
T t = default(T);
lock (EntityManager.lockObject)
{
if (instanceType != EntityManagerInstanceType.SingletonInstance || !EntityManager.entityManagers.ContainsKey(type))
{
t = (T)System.Activator.CreateInstance(type, true);
try
{
t.isSingleton = instanceType == EntityManagerInstanceType.SingletonInstance;
}
catch (Exception adapterException)
{
throw;
}
if (instanceType == EntityManagerInstanceType.SingletonInstance)
{
EntityManager.entityManagers[type] = t;
}
return t;
}
else
{
item = (T)EntityManager.entityManagers[type];
}
}
return item;
}
protected object ProcessRequest(string methodName, object request) { return new object(); }
}
public class PersonaEntityManager : EntityManager
{
protected PersonaEntityManager() { }
public PersonaResponseData UpdatePersona(PersonaUpdateRequestData requestData)
{
return (PersonaResponseData)base.ProcessRequest("Mdm.UpdatePersona", requestData);
}
}
public class PublisherWorkerRole : RoleEntryPoint
{
public bool UpdatePersona(PersonaUpdateRequestData contact, string MessageId)
{
PersonaEntityManager mgr = EntityManager.GetEntityManager<PersonaEntityManager>(EntityManager.EntityManagerInstanceType.NewInstance);
var resp = mgr.UpdatePersona(contact);
return resp != null;
}
}
What is the ideal approach in this scenario? Is this even testable short of setting up our own mock API and changing the application config for test to call our mock API instead?
Let me know if you need me to elaborate on this further.
One approach is to use something like ms shims or typemock to mock out the static call. This would reduce the impact to your production code, but if you're not already using them may require a financial investment. These libraries are able to intercept calls that other mocking frameworks can't so in addition to allowing you mock static calls, they would also allow you to create mock versions of the PersonaEntityManager which you would also need.
As you've mentioned in your comment below, the following approach doesn't work because you need to be able to Mock the PersonaEntityManager class so that you can intercept the call to UpdatePersona, which as it's not virtual standard mocking frameworks can't do. I've left the approach below for completeness, since it is the approach I would typically use to isolate a static dependency.
If you don't mind modifying your production code is to isolate the dependency behind a wrapper class. This wrapper class can then be injected into your code in the normal way.
So you would end up with some wrapper code something like this:
public interface IEntityManagerWrapper {
T GetEntityManager<T>(EntityManager.EntityManagerInstanceType instanceType) where T : EntityManager;
}
public class EntityManagerWrapper : IEntityManagerWrapper {
public T GetEntityManager<T>(EntityManager.EntityManagerInstanceType instanceType) where T : EntityManager {
return EntityManager.GetEntityManager<T>(instanceType);
}
}
The IEntityWrapper can be setup to be injected using Unity and then mocked using your mocking framework of choice to return mock instances of the other classes you depend on like PesonaEntityManager.
So, your production code would look like this:
public class MyProductionCode{
private IEntityManagerWrapper _entityManager;
public MyProductionCode(IEntityManagerWrapper entityManager) {
_entityManager = entityManager;
}
public void DoStuff() {
PersonaEntityManager pem = _entityManager.GetEntityManager<PersonaEntityManager>(EntityManager.EntityManagerInstanceType.NewInstance);
var response = pem.UpdatePersona(new PersonaUpdateRequestData());
}
}
And the test code would have looked like this (assuming you're using Moq):
[Test]
public void TestSomeStuff() {
var em = new Mock<IEntityManagerWrapper>();
var pe = new Mock<PersonaEntityManager>();
pe.Setup(x => x.UpdatePersona(It.IsAny<PersonaUpdateRequestData>())).Returns(new PersonaResponseData());
em.Setup(x=>x.GetEntityManager<PersonaEntityManager>(It.IsAny<EntityManager.EntityManagerInstanceType>())).Returns(pe.Object);
var sut = new MyProductionCode(em.Object);
sut.DoStuff();
}
The EntityWrapper class itself is pretty trivial, so I would tend to test it as an integration point, so use integration level testing to ensure it works both when it is written and if it is ever changed.
Hmm how about creating a proxy for that service. Expose necessary interface through proxy and inject provider (mocked or orginal) to it.

How to stub a static method?

I am working on a brownfield application and am currently refactoring part of it. I am trying to do this in a TDD fashion but am running into a problem. Part of the code I am testing does
var siteLanguages = from sl in SiteSettings.GetEnabledSiteLanguages() select sl.LanguageID;
where GetEnabledLanguages has the following signature
public static List<LanguageBranch> GetEnabledSiteLanguages();
it in turns calls data access code to retrieve the relevant information. Up untill now I have used a interface and DI to use a different stub implementation for these kind of dependencies during unit testing. But since the GetEnabledSiteLanguages method is static this will not work. What is the "correct" way to do it in this case?
you could create a object which implements an interface and inject an implementation of this into the class which uses the SiteSettings class. The interface declare the method with the same signature as the static method(s) you need to intercept. Then you could mock out the interface for tests and create a single implementation which delegates to the static method for the actual code:
public interface ISiteSettings
{
public List<LanguageBranch> GetEnabledSiteLanguages()
}
public class ActualSiteSettings : ISiteSettings
{
public List<LanguageBranch> GetEnabledSiteLanguages()
{
return SiteSettings.GetEnabledSiteLanguages();
}
}
... in the dependent class:
public class DependentClass
{
private ISiteSettings m_siteSettings;
public DependentClass(ISiteSettings siteSettings)
{
m_siteSettings=siteSettings;
}
public void SomeMethod
{
var siteLanguages = from sl in m_siteSettings.GetEnabledSiteLanguages() select sl.LanguageID;
}
}
What about making your method such as:
public static Func<List<LanguageBranch>> GetEnabledSiteLanguages = () => {
//your code here
};
Now it becomes first class object (as Func delegate) and a stub can replace it
Look at Moles framework.
You can use tools like JustMock, TypeMock or moles. These tools allow you to mock everythings like static methods.

Categories

Resources