I have a Container interface with a generic resolve method which, when implemented, resolves using Unity.
public interface IContainer
{
T Resolve<T>();
}
Currently there is a Mock Container class:
public class MockContainer : IContainer {
public T Resolve<T>()
{
return default(T);
}
}
But I want to use Moq for consistency and do the equivalent:
mockContainer
.Setup(container => container.Resolve<T>())
.Returns(default(T));
But I get 2 compile errors 'T' could not be found
Is the Moq syntax wrong, am I missing a reference or can this just not be done?
Edit
I know that mocking the container is not ideal. I could resolve each class one-by-one in my setup code.
My question is whether there is some Moq syntax to perform the equivalent of my actual container.
You usually can't do this (set up generic methods without specifying a type), but if you only want to return default(T) and don't care if the function is called at all, it's enough to simply create the mock without calling Setup:
var mockZincContainer = new Mock<IContainer>();
// works just fine
mockZincContainer.Object.Resolve<DateTime>(); // returns default(DateTime)
mockZincContainer.Object.Resolve<object>(); // returns default(object)
You can even return mocks instead of default(T) by changing the DefaultValue property of the mock from DefaultValue.Empty to DefaultValue.Mock.
You don't need to derive a mock object from your interface. So get rid of MockContainer.
In your unit test you should at that point know what types you want to test. So at that point, just give it a real type and tell it what to return.
i.e.
//arrange
mockZincContainer
.Setup(container => container.Resolve<ISomeInterface>())
.Returns(new ConcreteClassThatDerivesFromSomeInterface());
var testClass = new ClassToBeTested(mockZincContainer.Object);
//act
testClass.DoYourMethod();
//assert
mockZincContainer.Verify(c => c.Resolve<ISomeInterface>(), Times.Once);
Why would you mock the container? This is more of an integration concern. All of your code should be testable without having a container wire them up. Mocking the container to return a dependency which you are then passing in to consuming classes seems like a big waste of time to me.
Related
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.
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.
Disclaimer - this is not the same question as How to use FakeItEasy to assert a method was not called
Explanation
I have a piece of code which registers stuff with an IOC container, and I can use FakeItEasy in my tests to ensure that registrations are made.
I am trying to work out how to ensure that unexpected calls are not made.
Quick repo (problem boiled down to a couple of test classes - this is not a real implementation)
public class Foo
{
private readonly ICustomContainer m_CustomContainer;
public Foo(ICustomContainer customContainer)
{
m_CustomContainer = customContainer;
}
public void Bar()
{
m_CustomContainer.Register<IMyInterface, IMyImplementation>();
}
}
public interface ICustomContainer
{
void Register<TInterface, TImplementation>() where TImplementation : TInterface;
}
public class UnitTest1
{
[Fact]
public void Test1()
{
//Arrange
ICustomContainer fake = A.Fake<ICustomContainer>();
Foo objectUnderTest = new Foo(fake);
//Act
objectUnderTest.Bar();
//Assert
A.CallTo(() => fake.Register<IMyInterface, IMyImplementation>()).MustHaveHappened();
//A.CallTo(() => fake.Register<???>()).MustNotHaveHappened(); //Any generic parameter apart from <IMyInterface, IMyImplementation> must not have happened
}
}
The above test will pass - which is correct. If in the future I was to add another registration in the Bar(), it would still pass - which isn't so good as my test is only testing known scenarios.
What I am trying to achieve
So, given the interface defined above for ICustomContainer which is my IOC container, I would like to ensure that it is called only as expected.
What I have already investigated
Having used other mocking frameworks in the past such as TypeMock Isolator, I could set the fake object up to throw exceptions unless specific (expected) calls are made. I don't know if I can do this with FakeItEasy. Also TypeMock Isolator doesn't support .NET Core, so it is no good to me.
If I had a method that didn't use a generic parameter, I could get FakeItEasy to count the number of times that the method had been invoked, and expect that it had been invoked with any arguments in addition to testing the expected calls. That is certainly an option, but means that I have to create a facade over my interface (as an extension method or a wrapper, I guess) to take in type parameters rather than generic parameters, which means that I lose the pre-compile time warnings I get with the generic parameter constraint.
The actual question
How do I amend my test so that I can assert that an unexpected call was not made with any generic parameters other than those I was expecting using .NET Core / FakeItEasy / xUnit?
I may be oversimplifying, but it sounds like a Strict Fake can help you.
Make one, then explicitly allow whatever calls you want.
//Arrange
ICustomContainer fake = A.Fake<ICustomContainer>(x => x.Strict());
// allow just the registrations you want to
A.CallTo(() => fake.Register<IMyInterface, IMyImplementation>()).DoesNothing();
Foo objectUnderTest = new Foo(fake);
//Act
objectUnderTest.Bar();
//Assert
A.CallTo(() => fake.Register<IMyInterface, IMyImplementation>()).MustHaveHappened();
I'm trying to unit test a method and mock the method call inside it:
class LoginViewModel
{
public bool LogUserIn(string hashedPassword)
{
//Code
if (loginSuccessful)
{
GoToMainMenu(); // I WANT TO MOCK THIS CALL.
return true;
}
return false;
}
}
so I want to mock the GoToMainMenu() function call, as this is only for navigation and I get an exception thrown here when I try to run my test.
I've tried using NUnit.Mocks:
[Test]
public void Log_User_In_Will_Return_True()
{
DynamicMock mockView = new DynamicMock(typeof(LoginViewModel));
mockView.ExpectAndReturn("GoToMainMenu", null);
LoginViewModel loginVM = (LoginViewModel)mockView.MockInstance; //ArgumentException
Assert.AreEqual(true, loginVM.LogUserIn("aHashedPassword"));
}
But this gives me an ArgumentException.
I've spent a lot of time trying different ways to make this work and have also tried Rhino Mocks but couldn't get my head around how to mock this call. Can anyone help with this? I haven't tried Moq but suspected it to be similar to Rhino Mocks.
In your current setup this what you're trying to do is impossible. Few things to fix:
start using stable version of Rhino (like 3.6). Better yet, upgrade to Moq which is a newer framework
make GoToMainMenu method virtual (and at least protected)
Your test then (Rhino 3.6) should look like this:
var mock = MockRepository.GenerateMock<LoginViewModel>();
Assert.AreEqual(true, mock.LogUserIn("aHashedPassword"));
Few things to note here. Any non-virtual method called will use your original implementation (like LogUserIn). Every virtual method on the other hand will be replaced by RhinoMocks with default (do nothing) implementation, which should be enough to make test pass. The same test in Moq:
var mock = new Mock<LoginViewModel>();
Assert.AreEqual(true, mock.Object.LogUserIn("aHashedPassword"));
The way it works like this (need to have virtual methods) is because when creating a mock, both Rhino and Moq will generate in memory assembly and create new type there, deriving from your type (in your case, LoginViewModel). Derived type (mock) can then replace any method of original type given it's virtual (standard C# mechanism) or type is interface - then the mock simply implements the interface.
Here is my code below. I am using the Moq library. Instead of letting Moq create an instance for me. I need to flat into a type to pass to someone to create instance later. How do I do that?
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.Bar()).Returns(true);
// Test the actual method
DoSomething(mockedIStateProvider.Object.GetType());
// Not my code, it's a 3rd party library, not allowed to change
public void DoSomething(Type type)
{
Activator.CreateInstance(type);
...
...
}
You can't with Moq. The Activator will always create a new instance which you won't have access to so you won't be able to setup the mocking behaviour you want.
That being said, you can probably get the behaviour you want by writing your own stub implementation that will always do what you want.