I've made refactoring if our repository factory to make it more generic and right now the method creating repositories looks like that:
public TRepository CreateRepository<TRepository>(params object[] parameters)
where TRepository : class
{
if (_serviceProvider == null)
throw new ArgumentNullException(nameof(_serviceProvider));
return ActivatorUtilities.CreateInstance<TRepository>(_serviceProvider, parameters);
}
In my production code I am using it like so and it works like charm:
_concreteRepo = repoFactory.CreateRepository<ConcreteRepo>();
But when I am trying to refactor unit tests as well I am having difficulties setting up the factory, this is how I do it but it doesn't work.
public class Tests
{
// Since I am using Moq I can't mock anything but abstract types thus having problems with type conversion in set up.
protected readonly Mock<IConcreteRepository> _concreteRepositoryMock = new Mock<IConcreteRepository>();
protected readonly Mock<IRepositoryFactory> _factoryMock = new Mock<IRepositoryFactory>();
[SetUp]
public void SetUp()
{
// If I don't cast concreteRepositoryMock compiler complains that cannot convert from abstract to concrete repository.
// If I cast it fails and returns null.
_factoryMock.Setup(f => f.CreateRepository<ConcreteRepository>())
.Returns(_concreteRepositoryMock.Object as ConcreteRepository);
}
}
Any idea how can workaround it? Seems like my CreateRepository method is returning concrete types, but mocking I cannot mock my concrete repository.Also I couldn't pass abstract types to CreateRepository, because CreateInstance requires concrete types.
I think your issue is that you expect the Mock object:
protected readonly Mock<IConcreteRepository> _concreteRepositoryMock = new Mock<IConcreteRepository>();
To be instance of ConcreteRepository, which is wrong assumption.
_concreteRepositoryMock.Object is IConcreteRepository
This should say "TRUE" while
_concreteRepositoryMock.Object is ConcreteRepository
This should say "FALSE".
You have to either switch your PROD code to be happy with abstraction (IConcreteRepository) or mock the final class
protected readonly Mock<ConcreteRepository> _concreteRepositoryMock = new Mock<ConcreteRepository>();
in your mock (note that mocking concrete classes is usually not easy - you need all mocked methods to be virtual etc.).
Actually I found workaround to this which I am relatively happy at the moment, but if any other suggestions appear I would love to hear them.
So problem was that my CreateRepository was returning concrete implementation while it had to return abstraction because all my mocks are abstractions (because Moq mocks only abstractions). Therefore I modified my method as follows:
TInterface CreateRepository<TRepository, TInterface>(params object[] parameters)
where TRepository : class, TInterface where TInterface : class;
And this guaranteed compile-time safety for my set up method and success afterwards. I do find it somewhat cumbersome, but I can live with it for now.
NOTE: You can always do extension method within internal class in your testing assembly and copy&paste the code from production method, this way you won't pollute your production code, however, this can be problematic if someone tries to change the production method without changing the test one, this is why I choose to "pollute" my production code for the sake of safety.
Related
We use UnityAutoMoq for mocking most of our interfaces in our unit tests, but I've recently run into a situation where we want to use a test framework to more completely simulate the actual behavior (call it an integration test if that helps you accept what I'm doing).
I expected UnityAutoMoq to let me register concrete mappings instead of allowing the UnityAutoMoqContainer to defer to mocking the interface. This holds true to everything I've tried except for generic interfaces. In case you're visual like me, here's a snippet of what I'm trying:
public static void Register(IUnityContainer container)
{
...
container.RegisterType(typeof(IService<>), typeof(TestFrameworkService<>),
new HierarchicalLifetimeManager(), new InjectionFactory(Create));
...
}
private static object Create(IUnityContainer container, Type type, string name)
{
var T = type.GetGenericArguments().Single();
return new TestFrameworkService<T>();// For simplicity, pretend this works
}
As you can see from above, I'm registering the generic interface to a generic concrete, then depending upon the injection factory to resolve it using the incoming type (the actual implementation was omitted for simplicity). This works with a normal UnityContainer, returning the expected concrete. The UnityAutoMoqContainer returns a mock instead, bypassing the injection factory completely.
Has anyone tried anything like what I'm trying to accomplish? Any ideas?
I found that the problem lies in the underlying BuilderStrategy. Here's a snippet from UnityAutoMoqBuilderStrategy.
public override void PreBuildUp(IBuilderContext context)
{
var type = context.OriginalBuildKey.Type;
if (autoMoqContainer.Registrations.Any(r => r.RegisteredType == type))
return;
if (type.IsInterface || type.IsAbstract)
{
context.Existing = GetOrCreateMock(type);
context.BuildComplete = true;
}
}
Bottom line is that the builder strategy sees that the interface isn't registered and intercepts its creation. This is because generic type definitions aren't equal to the generic types, themselves.
I looked into AutoMoq, which was far more recently updated, but it suffers from the same interception limitation that prevents the injection factory from firing.
For reference, here are the automocking libraries that I researched:
https://github.com/thedersen/UnityAutoMoq
https://github.com/rajgit31/UnityAutoMoq
https://github.com/darrencauthon/AutoMoq
If someone has a recommendation, then please let me know, otherwise I'll consider this the answer.
I have an interface like this
public interface IConnection
{
Strategy Gc { get; }
bool IsConnected();
bool Connect();
}
I want to unit test methods of a class that uses this interface. Now I want to set Gc but it happens to be readonly. Is there a way to set Gc field without making changes to this interface class?
I am using MS fakes and Nsubstitute for unit testing. However, apparently none provides a solution. PrivateObject does not work either.
Changing Interface is not an option. Suggest better solutions.
With NSubstituteit is quite easy. First create a mock for your interface:
var mock = Substitute.For<IConnection>();
Now you can mock the member by setting any return-type for the property:
mock.Gc.Returns(Substitute.For<Strategy>());
Finally provide that mocked instance as parameter to the service depending on that instance, for example:
var target = new MyClassToTest();
target.DoSomething(mock); // mock is an instance of IConnection
Now whenever your method is called it returns a dumm-instance for Strategy. Of course you can also set any other arbitrary return-type within the Returns-statement. Just have a look at http://nsubstitute.github.io/help/set-return-value for further information.
I have this scenario: an interface with 2 methods
the 2 methods take requests and return response
Methods contain functionality inside (check permissions and validate request and get data from database using entity framework.
But I want to test the methods and not just the interface.
I've tested the interface successfully but now I want to enter the method and test inside it.
Code example:
public interface IMyInterface
{
[OperationContract]
responseObject GetData(Service<RequestObject> request);
}
public class MyConcreteClass : IMyInterface
{
public responseObject GetData(Service<RequestObject> request)
{
CheckForNull(request);
ValidateMethod(request);
//connect to db
using(var context = new contextEntity)
{
//get data
}
}
}
Now, I want to test the check nulls, permissions and data access, is it possible? Or do I have to extract interface from the internal methods?
PS, this is for my unit testing. I'm trying to eliminate external dependencies.
please explain in detail
Unit testing private methods should not be needed directly, only indirectly via public methods. If you think you testing a public method isn't enough precise, it might be that the method and the class are too complicated already.
In that case consider creating one or more new classes where the new code is located. That way you can unit test your code via public method. The added benefit is that your code is probably better in terms of Single responsibility principle.
The reason for mocking is so that you can control behaviour; in this case, I'm going to go out on a limb and guess that Service<RequestObject> doesn't actually have any behaviour, and therefore it doesn't actually need to be mocked. So it can probably just be passed as-is in any tests.
However, if it does have behaviour, and that behaviour crosses an architectural boundary (let's say in the GetData method you are calling some method on the request parameter that will make a network call, or access the file system, etc.) then you do need to mock it. But you can do that easily enough:
public interface IService<RequestObject>
{
//put method and property signatures of Service<RequestObject> here
}
public class ServiceObject:Service<RequestObject>, IService<RequestObject>
{
public ServiceObject(RequestObject request): base(request){
//or however the Service<Request> object is instantiated.
};
}
Then change GetData to take an IService<RequestObject>; now your calling code can instantiate a ServiceObject in place of a Service and pass it to the GetData method. Plus you can Mock any methods on the interface as you need. Obviously if you don't control the calling code, that's a problem since whoever is writing that code needs to do it, but that's a conversation you will need to have with them :)
In terms of testing the internal operations,you need to look at how you can abstract any dependent behaviours used by the GetData method - for example, the contextEntity, the CheckForNull, the ValidateMethod, etc - all of these are candidates to be extracted into their own abstractions and injected into the MyConcreteClass as dependencies, e.g.:
public class MyConcreteClass: IMyInterface
{
readonly INullChecker _nullChecker;
readonly IValidator _validator;
readonly IContextEntity _context;
public MyConcreteClass(INullChecker nullChecker, IValidator validator, IContextEntity _context)
{
_nullChecker = nullChecker;
_validator = validator;
_context=context;
}
public responseObject GetData(Service<RequestObject> request)
{
_nullChecker.Check(request)//**;
_validator.Validate(request);
var result = _context.DoSomethingWith(request);
return result;
}
}
Now you can write tests for MyConcreteClass and use mocked implementations of the dependencies, to ensure that the GetData method correctly uses them.
**and I will guess that this can be replaced with a simple if request==null throw new ArgumentNullException() which is cleaner and simpler anyway.
I am attempting to mock (using Moq) a classes and interfaces that are defined in a third party SDK. Here's a simplified example of what they look like:
public interface IVehicle
{
string Type { get; }
}
public class Vehicle
{
public string Type { get; }
}
public class Jeep : Vehicle, IVehicle
{
}
I can easily mock the interface like so:
var mockVehicle = new Mock<IVehicule>(MockBehavior.Strict);
mockVehicle
.SetupGet(v => v.Type)
.Returns("My custom vehicle");
but I need to write a unit test specific to the Jeep class and I can't figure out how to mock it.
My first attempt:
var mockJeep = new Mock<Jeep>(MockBehavior.Strict);
yielded the following error:
Moq.MockException: IVehicle.Type invocation failed with mock behavior Strict.
All invocations on the mock must have a corresponding setup.
which is understandable since I haven't setup the Type property.
My second attempt:
var mockJeep = new Mock<Jeep>(MockBehavior.Strict);
mockJeep
.SetupGet(v => v.Type)
.Returns("Jeep");
yielded the following error message:
System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: v => v.Type
which is also understandable since the Type property on the Vehicle class is not virtual.
So my question is: is there a way to setup the Type property when mocking the Jeep class?
The best Moq can do in this case is create a proxy as a derived class of Jeep but it cannot override the non-virtual Type property. Remember that when you attempt to create a Mock with Moq, the framework generates a class that either implements the target interface or derives from the target class.
Microsoft Fakes work well with Moq provided that you have the Visual Studio license level to access it.
Since this is a rather generalized question, I'm going to suggest a different approach. Mocking / Faking / Stubbing a class or interface that you don't control is generally difficult. Furthermore, this typically leads to replicating someone else's functionality in your mock instance.
A better approach is to isolate interaction with the external library into a wrapping class that you control the interface and implementation of. This will allow you to easily mock/fake/stub your interface for testing consumers of your interface.
This still leaves the question of what to do with the isolation layer class. For this, you'll need to do more of an integration test that actually exercises both your wrapping class and the external class. Then, verify that you get the expected behavior from the combination of your class and the external classes you're wrapping.
So my question is: is there a way to setup the Type property when mocking the Jeep class?
The short answer is no, you cannot Mock a non virtual member using Moq.
However, I don't think there's any reason in this case to mock anything, since there isn't any behaviour to mock. The only member you have there is a simple string property. So even if you could, you probably shouldn't.
If you are trying to test the Jeep class, just test it directly
without mocking any of its members; mocking should only be used when you need to control the behaviour of one of the dependencies of the System Under Test (SUT)
If you are passing the Jeep
class to another method as a dependency in order to test that method, you can just
new up a Jeep instance and pass it in your test in this case; since it doesn't
have any boundary-crossing behaviours (network calls, etc) then there
is no need to mock it.
You might also consider that if it's the second case, you ought to be able to pass an IVehicle instead of a Jeep, in which case mocking is back on the table (although as mentioned, there is no apparent need in this case)
Incidentally, your hierarchy looks a little off - why does Vehicle not itself implement IVehicle?
i.e.
public interface IVehicle
{
string Type { get; }
}
public class Vehicle: IVehicle
{
public string Type { get; }
}
public class Jeep : Vehicle
{
}
Then Jeep will already be both a Vehicle and an IVehicle :)
disclaimer: I work at Typemock.
By using Typemock Isolator you will be able to mock non-virtual methods and won't need to change your code in order to do so, in this specific example you can fake an instance of Jeep and then modify his methods behavior.
Here is an example for a test that mock Jeep:
[TestMethod]
public void CallFakeJeepType_WillReturnWantedString()
{
var jeep = Isolate.Fake.Instance<Jeep>();
Isolate.WhenCalled(() => jeep.Type).WillReturn("fake jeep");
var result = Jeep.DoSomthing(jeep);
Assert.AreEqual("fake jeep", result);
}
note: if the Jeep.Type had a setter as well you could use typemock's True property and the test will look like this
var jeep = Isolate.Fake.Instance<Jeep>();
jeep.Type = "fake jeep";
I have an interface with a number of generic methods. These methods perform operations based on the type of data that is passed in. How do I mock this with NSubstitute? At the moment, I had to resort to using a concrete class instead of a mock since I cannot handle all possible types that the method will be called with.
public interface IInstanceSource
{
bool CanCreate<T>();
T Create<T>();
void Register<T>(Func<T> creator);
}
public static IInstanceSource GetInstanceSource()
{
var _data = new Dictionary<Type, Func<object>>();
var a = Substitute.For<IInstanceSource>();
//code below fails since T is not defined. How do I make the code below accept any type?
a.WhenForAnyArgs(x=>x.Register(Arg.Any<Func<T>>)).Do(x=> { /* todo */});
a.CanCreate<T>().Returns(x => _data[typeof (T)]);
return a;
}
thanks.
NSubstitute doesn't support setting up multiple instances of a generic method automatically.
The way we'd normally see IInstanceSource used in a test is to configure it for a specific bit of code under test, so T would be known. If a single fixture needed to work for a few different Ts, we could make configuration simpler by having a helper method like ConfigureInstanceSource<T>() which would do the configurations steps for a specific T.
In your case though it seems like you want a fixed behaviour for all fake instances of IInstanceSource, in which case I believe you are going the right way about it by hand-coding your own test double.