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.
Related
I have class MyService that depends on ABCService (Nuget package/sdk)
public class MyService
{
private readonly ABCService _abc;
public MyService(ABCService abc)
{
this._abc = abc;
}
public async Task Run(string id)
{
// some logic
var result = await this._abc.DoSomething(id);
// some logic
}
}
ABCService looks something like this:
public class ABCService
{
internal ABCService(string someConnectionString, object someSettings)
{
// ... initialization
}
public static CreateFromConnectionString(string someConnectionString, object someSettings)
{
// some logic
return new ABCService(someConnectionString, someSettings);
}
}
Mocking class this way would not work and throws exception. "Parent does not have a default constructor."
var mock = new Mock<ABCService>();
var myService = new MyService(mock.Object);
How should I approach this? Is there a way to mock such classes?
The only thing that comes to my mind is creating interface IABCService and then injecting it in the constructor of MyService
public class IABCService
{
Task DoSomething(string id);
}
public class MyService
{
private readonly IABCService _abc;
public MyService(IABCService abc)
{
this._abc = abc;
}
}
And then I could do this:
var mock = new Mock<IABCService>();
var myService = new MyService(mock.Object);
Popular isolation frameworks such as Moq, NSubstitute or FakeItEasy are constrained. They can substitute only virtual methods. To use them, you will have to use the interface, as you already guessed. This is the recommended way to easily maintain loose coupling and testability.
There are bunch of unconstrained mocking frameworks: TypeMock Isolator, JustMock, Microsoft Fakes (all three are paid) and free open source Prig, Pose, Shimmy, Harmony, AutoFake, Ionad.Fody, MethodRedirect. They allow to mock non-virtual members, including private, static, etc.
Some of them allow you to work wonders, but you should not get too carried away with using them, because in the end it can lead to bad architecture.
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.
I have a job in which I have an IDisposable DbContext. I would like to unit test this job without hitting in a database. What options do i have to do this?
Im using the default Fakes assembly' of microsoft.
My job:
public void Work()
{
do
{
//code here
using (var repository = new Repository<User>())
{
repository.Save(user);
}
} while (true);
}
I'm trying to test and in this part of the test it fails because it actually creates a new instance of the Repository class.
My test Method:
using (ShimsContext.Create())
{
Data.Repository.Fakes.ShimRepository<Domain.Fakes.ShimUser>.Constructor = (a) => { };
Data.Repository.Fakes.ShimRepository<Domain.Fakes.ShimUser>.AllInstances.SaveT0 = (a, b) =>
{
};
var service = GetService();
service.Work(); //Throws exception
}
How can I fake this Save method?
You've violated DIP here, making unit testing your service far more difficult than it should be. You should also avoid generic repositories and favour role interfaces.
Instead, inject an abstraction into your service of your repository, e.g. IUsersRepository which defines your Save method. Then in your unit test of the service you can simply use a stub implementation of IUsersRepository.
Fakes tend to reveal that your code is not properly following the D in SOLID since you are creating dependencies inside your class instead of passing them in.
A much better pattern would to create an ISaveRepository interface that in turn implements IDisposable with an exposed Save() method. You should then inject an instance of your repository into your class. This will allow you to satisfy the using statement testing, as well as implement a mock that defines a .Save() method that does not hit the database.
public class Test
{
private readonly ISaveRepository _userRepository;
public Test(ISaveRepository userRepository)
{
_userRepository = userRepository;
}
public void Work()
{
using (_userRepository)
{
var cont = true;
do
{
_userRepository.Save(new User());
cont = false;
} while (cont);
}
}
}
public interface ISaveRepository : IDisposable
{
void Save<T>(T model);
}
public class Repository<T> : ISaveRepository
{
public void Dispose() { }
public void Save<TT>(TT model) {}
}
public class User {}
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
I want to write tests for a program that is coded by someone else. But I have some problems while writing tests. I can't understand exactly how to fake some objects. I searched and found Unit Test for n tier architecture but It doesn't help me. For example, I want to write a test for code below (I know It is a dummy code for just clarification)
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
DAL customerDal = new DAL();
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
I just want to test FetchCustomersByName but there is connection with DAL. I think creating stub class but In this case I have to change my original code. And it was coded by someone else. How can I write a test for this method?
Thanks in advance.
Don't unit test the data access layer. Write integration tests for it.
Mocking the dependencies in the DAL isn't just worth the trouble as it doesn't guarantee anything.
If you think about it, the DAL have dependencies on the SQL dialect and the database schema. Therefore your unit tests might work just fine. But when you run the real solution it can still fail. The reason can be that your SQL queries are incorrect or that the one of the class property types doesn't match the table column types.
unit tests are typically written for business logic. One thing that they catch is errors that doesn't generate exceptions such as incorrect conditions or calculation errors.
Update
Ok. So your example actually contains business logic. The method name fooled me.
You have to change the way you create your DAL classes. But you don't have to use constructor injection like Jack Hughes suggests. Instead you can use the factory pattern:
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
var customerDal = DalFactory.Create<CustomerDal>();
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
That's bit easier since now you can just use "replace all" to change all var customerDal = new CustomerDal() to var customerDal = DalFactory.Create<CustomerDal>();
In that factory class you can call different implementations
public class DalFactory
{
public static IDalFactory Factory { get set; }
static DalFactory()
{
Factory = new DefaultDalFactory();
}
public static T Create<T>() where T : class
{
return Factory.Create<T>();
}
}
public interface IDalFactory
{
T Create<T>() where T : class
}
public class DefaultDalFactory : IDalFactory
{
public T Create<T>() where T : class
{
return new T();
}
}
The code isn't beautiful, but it solves your case with minimal refactoring. I suggest that you start with that and then try to change your coding standards so that constructor injection is allowed.
To get it working in your tests you can use the following implementation. It uses [ThreadStatic] to allow multiple tests to run at the same time.
public class TestDalFactory : IDalFactory
{
[ThreadStatic]
private static Dictionary<Type, object> _instances;
public static Dictionary<Type, object> DalInstances
{
get
{
if (_instances == null)
_instances = new Dictionary<Type, Object>();
return _instances;
}
}
public static TestDalFactory Instance = new TestDalFactory();
public T Create<T>() where T : class
{
return (T)_instances[typeof(T)];
}
}
Next in your tests you can configure the DAL factory to return a mock by doing the following:
[TestClass]
public class MyBusinessTests
{
[TestInitialize]
public void Init()
{
DalFactory.Instance = TestDalFactory.Instance;
}
[TestMethod]
public void do_some_testing_in_the_business()
{
TestDalFactory.Instance.DalInstances[typeof(CustomerDal)] = new MyNewMock();
//do the testing here
}
}
Using constructor injection of the DAL would allow you to stub the DAL layer. Ideally you would inject an interface. Mocking concrete classes is a bit of a pain with the tools I've used. Commercial mocking tools may well be better suited to mocking concrete classes but I've not used any of those.
class YourClass
{
private DAL customerDal;
public YourClass(DAL theDal)
{
customerDal = theDal;
}
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
// don't create the DAL here...
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
}
[Test]
public void TestMethodHere()
{
// Arrange
var dalMock = Mock.Of<DAL>();
// setup your mock DAL layer here... need to provide data for the FetchByName method
var sut = new YourClass(dalMock);
// Act
var actualResult = sut.FetchCustomersByName(new CustomerObject());
// Assert
// Your assert here...
}