AutoMoqer: Passing parameters into constructors - c#

When I'm in need to mock some class that goes like this:
public class Dummy
{
private readonly int _someInt;
private readonly int _someOtherInt;
private readonly IFoo _foo;
public Dummy(int someInt,int someOtherInt, IFoo foo)
{
_someInt = someInt;
_someOtherInt = someOtherInt;
_foo = foo;
}
}
I use Moq to do something like this:
[Test]
public void ShouldCreateADummyInstance()
{
var someInt = 1;
var someOtherInt = 2;
var mockFoo = new Mock<IFoo>();
var dummy = new Dummy(someInt, someOtherInt, mockFoo.Object);
//And so on...
}
But when I use AutoMoq I can't specify a different int for each dependency (I mean someInt and someOtherInt) into my constructor because AutoMoqer.SetInstace(instanceIWantToUse) sets the same specified instance each time that has to supply that dependecy.
Do you know how can I specify a different int for someInt and someOtherInt in order to keep using AutoMoqer in my tests ?
Thanks, hope you can help me out!

Full disclosure: I've never used AutoMoq (though I did just sign up to follow it on GitHub since it looks intriguing and I like things that cut down on boilerplate).
That said, it looks like the AutoMoq tool was designed for a different use case than yours. It appears that he uses it to "future proof" against broken unit tests if another constructor injected dependency is added, and to be able to generate a default object with something there for the dependencies, presumably to avoid null reference exceptions.
I would assume after reading the AutoMoq project page that if Darren were writing your particular unit test, he would probably just use Moq out of the box. That is, for that particular test, you should probably go with the test that you have posted. AutoMoq appears to aim at supplying sensible default behavior for when you don't want to bother specifying all of your dependencies in a test. But in your case, you do want to specify those particular dependencies.
Just because you use regular Moq for that particular test doesn't mean that you can't use AutoMoq for other tests. The rest of your tests (where both ints are zero or whatever) will be future-proofed, but you may just have to live with that one breaking if you add another constructor parameter to your Dummy class.
(You could also always snag the source code for AutoMoq and modify it to your needs).

Solution similar to Moq
You can create an instance of Dummy in AutoMoq very similar as you do in Moq.
This does not future proof your testcode against changes in the constructor parameters, but may still be acceptable.
var mocker = new AutoMoqer();
var fooMock = mocker.GetMock<IFoo>();
var dummy = new Dummy(1, 2, fooMock.Object);
// test something about dummy
Solution with AutoMoq
If you really want to future proof your TestCode, then it may be neccessary to change the constructor to depend on interfaces.
interface IDummyParameters {
int SomeInt {get;set;}
int SomeOtherInt {get;set;}
}
public class Dummy {
public Dummy(IDummyParameters parameters, IFoo foo){
...
}
}
Then you can create your Dummy class with AutoMoq like this:
var mocker = new AutoMoqer();
mocker.GetMock<IDummyParameters>.Setup(x => x.SomeInt).Returns(1);
mocker.GetMock<IDummyParameters>.Setup(x => x.SomeOtherInt).Returns(2);
// notice how this code does not say anything about IFoo.
// It is created automatically by AutoMoq
var dummy = mocker.Create<Dummy>();

Related

Unit Testing with Mock. Parent does not have a default constructor

I'm trying to write a unit test and coming across the error,
Parent does not have a default constructor. The default constructor must be explicitly defined.
I've had a look to see what this means and I see it mentioned that there is no public constructor. Only thing is, my code does have this so I'm confused why there is this error.
This is the unit test..
public void CalculateVat_ReturnsCorrectAmount()
{
// Arrange
const decimal expectedResult = 2;
_mockSingleValueParameter = new Mock<ISingleValueParameterService>();
_mockItemCache = new Mock<ItemCache>();
_mockReferenceDataService = new Mock<ReferenceDataService>();
_Calculator = new CostCalculator(_mockSingleValueParameter.Object, _mockItemCache.Object,
_mockReferenceDataService.Object);
// end
//.....
}
The line
_calculator = new CostCalculator(_mockSingleValueParameter.Object, _mockItemCache.Object,
_mockReferenceDataService.Object)
is the one that throws the error.
This is the constructor of CostCalculator..
public CostCalculator(
ISingleValueParameterService singleValueParameterService, ItemCache cache, ReferenceDataService referenceDataService);
{
_itemCache = cache;
_singleValueParamService = singleValueParameterService;
_refDataService = referenceDataService;
}
There is other code in the project that looks just like this as well but works..I can't understand what the difference is between them.
TIA!
If you want to mock a concrete class instead of an interface, it must have a default constructor (i.e. no parameters) and any methods you want to perform setups on must be virtual.
In your case it looks like either ItemCache or ReferenceDataService (or both) are lacking default constructors.

force relay to mocking framework

I would like to create a customization that configures AutoFixture to pass types it DOES have implementations for off to Moq instead. How can I do that generically?
To clarify, consider:
public class test
{
public string foo;
public test(IDictionary<string, string> stuffing)
{
foo = stuffing["bogus"];
}
}
[TestMethod]
public void testInjection()
{
var fixture = new Fixture();
bool didThrow;
try
{
var sut = fixture.Create<test>();
didThrow = false;
}
catch
{
didThrow = true;
}
Assert.IsTrue(didThrow);
}
The test passes. AutoFixture has provided me with a dummy collection compatible with IDictionary. I would like the test to fail... specifically, I'd like to hand the IDictionary off to Moq and get something that doesn't complain about missing keys by default.
I'd like to use something like fixture.UseAutoMoq().ForceRelay<Dictionary<string,string>>().
I'm also open to better suggestions... but consider the test class sealed. I'm testing into code that uses this pattern a lot and I want a test convention around it.
To do what you ask for, you can take the MockRelay added by AutoMoqCustomization and move it in front of the well-known-collections-builders:
[Fact]
public void PassByMovingAutoMoqRelay()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var relay = fixture.ResidueCollectors.OfType<MockRelay>().Single();
fixture.Customizations.Add(relay);
var sut = fixture.Create<MyClass>(); // Doesn't throw
}
However, I don't think it's a good idea, as most of the .NET collection interfaces are big fat LSP violations, and there's no guarantee that auto-mocking them will produce meaningful behaviours - I'd expect the opposite to be the case.

How to mock class members in C#?

I'm trying to use FakeItEasy to mock an object that is a member of a C# class I'm creating.
The FakeItEasy documentation indicates that you fake an object in a way similar to this:
private static var m_physics = A.Fake<IPhysics>();
That is, using the "var" keyword.
However, in this case the C# compiler doesn't like the fact that var is being used in a non-local context. I get this error:
The contextual keyword 'var' may only appear within a local variable declaration
Can't I mock an object that's not local?
I think you're missing the point of mocks/stubs. Mocks and stubs are used for testing when you don't want the subject under test to pass or fail depending on other components that it depends on. So what you do is swap explicit implementations of these out for mocks/stubs of these dependencies that you can completely control within the test.
class Foo {
public Foo(IBar bar) { }
public object M() { // do something with IBar }
}
Here Foo has a dependency on IBar. We want to test Foo.M. We don't want the test to pass or fail based on whether or not the concrete implementation that we give to Foo of IBar is working or not.
[Fact]
public void MDoesWhatItIsSupposeToDo() {
var foo = new Foo(new Bar());
object expected = // expected result
Assert.Equal(expected, foo.M());
}
If Bar is broken this test could fail even though Foo might be coded perfectly correctly. So you sub in a mock/stub to preven this
[Fact]
public void MDoesWhatItIsSupposeToDo() {
var bar = A.Fake<IBar>();
// set up bar to do what is expected of IBars
var foo = new Foo(bar);
object expected = // expected result
Assert.Equal(expected, foo.M());
}
Now this test only passes or fails if Foo is coded correctly or not, independently of whether or not your concrete implementations of IBar are correct.
This is the point of mocks.
So all of this is to say, you are not using mocks properly.
Can't I mock an object that's not local?
You can, but not in the way that you are doing. First, fields can't be implicitly typed. Secondly, you don't mock the field explicitly like you've done. Instead you do it like this:
class Whatever {
private IPhysics m_physics;
public Whatever(IPhsyics physics) { this.m_physics = physics; }
}
Then:
var physics = A.Fake<IPhysics>();
var whatever = new Whatever(physics);
You can only use the 'var' keyword in a local context like a function block. You cannot declare a class member as a 'var'.

Refactoring code that uses new operator to be more testable

I have the following code and am trying to unit test it:
public override IRenderable GetRenderable()
{
var val = SomeCalculationUsingClassMemberVariables();
return new EquationRenderable(val);
}
It seems like I want to use a factory here so I can separate the creation of the IRenderable from this class. The problem is that I have many of these classes that create different IRenderables that are constructed in different ways, so I would need to implement a new factory method for each one. What is the best way to solve this problem?
Good question.
First of all, feeling tempted to use AbstractFactories everywhere smells a bit as DI container is not used the "right" way or design could be improved.
But sometimes I've also come across this problem. I see following:
using AbstractFactory/Factory and Inject it. For C# you have to advantage that you can pass delegates, acting as interface for the creation of instance.
'new' is OK, simply test the output of 'new'.
Stub the call of 'new' inside extracted method (hacky!!)
Injection got mentioned already so I won't repeat. I am more into Java so please excuse some syntax errors.
Test the output of 'new'
I often use this, if the 'new' created instances are domain-objects and not services. Because it is returned directly in method I can test the direct output with my test.
Prod-Code:
...
public override IRenderable GetRenderable()
{
var val = SomeCalculationUsingClassMemberVariables();
return new EquationRenderable(val);
}
Test Case:
...
[Test]
public void test_new()
{
SUT sut = ...;
IRenderable r = sut.GetRenderable();
assertTrue(r instanceof EquationRenderable);
}
Stub the call of 'new' itself
Testing direct output from above is only possible if you somehow get it as return value. Things get more complicated if the "sideeffect" of your code are indirect outputs, which you can't sense directly by the return value. If so I often extract-method of the new-creation and then have it under control in my test. This is yucky and I more use it to go safe with my test and start more refactoring later (DI and factories). I sometimes do this in legacy code where services are created with 'new' directly and refactoring to DI is too risky without tests.
Prod-Code:
...
public override IRenderable GetRenderable()
{
var val = SomeCalculationUsingClassMemberVariables();
return createEquationRenderable();
}
public IRenderable createEquationRenderable()
{
return new EquationRenderable(val);
}
Test Case:
...
class Stubbed : SUT
{
boolean called = false;
public override EquationRenderable createEquationRenderable()
{
called=true;
return MyMock();
}
}
[Test]
public void test_new()
{
Stubbed sut = new Stubbed();
sut.GetRenderable();
assertTrue(sut.called);
// do further stuff on MyMock
}
I know, the example is overkill and a bit senseless, it is just for describing the idea. I am sure above could be shortcutted with mocking-frameworks for C#. Anyway testing the return-value direct output is more trivial and better approach here.
Maybe you have a more detailed example?
depending on the uniformity of your concrete IRenderable constructors you can use the following pattern for factory creating
public IRenderable CreateInstance<T>(object calculation) where T : IRenderable
{
Activator.CreateInstance<T>(new[] { calculation });
}
or if you have many different constructors you can use the params keyword to pass arbitrary amounts of arguments
public IRenderable CreateInstance<T>(params object[] args) where T : IRenderable
{
Activator.CreateInstance<T>(args);
}
To be able to do some kind of runtime check of the arguments you use this code before calling the Activator.CreateInstance
var types = args.Select(o => o.GetType()).ToArray();
var c = typeof(T).GetConstructor(types);
if (c == null)
{
throw new InvalidOperationException("No matched constructor")
}
A better way may be to simply unit test the code as is instead of refactoring it. Technically, this can be done by using a suitable mocking tool such as TypeMock Isolator or Microsoft Moles (there is a third one which I don't remember now).

How to assert a private method on concrete class is called (TypeMock/NMock/etc..)?

I am trying to write a unit test for the 'IsUnique' function in the class below that looks like this:
class Foo
{
public bool IsUnique(params...)
{
ValidateStuffExists(params);
return CheckUniqueness(params);
}
private void ValidateStuffExists(params)
{
//does some validation
}
private bool CheckUniqueness(params)
{
//does logic to determine if its unique per params
return result;
}
}
The only thing I want to test here is that ValidateStuffExists and CheckUniqueness is called and passed the arguments. That's all this function does so it's all I'm going to test (I'll bend the 'test public behavior only' psuedo-rule and test the private methods here, because its either have one big complicated method/tests or testing 2 private methods).
I am open to any mocking library. I use NMock and didn't think it was up for the Task - so I downloaded TypeMock as I've done reading and heard that this was the best and that it could mock out even concrete classes / non interface method calls...
I'm doing something like this in my test and it throws exception at the 'Isolate.WhenCalled' line:
CrmEntityUniqueValidator_Accessor target = new CrmEntityUniqueValidator_Accessor(); // TODO: Initialize to an appropriate value
DynamicEntity entity = null; // TODO: Initialize to an appropriate value
string[] propertyNames = null; // TODO: Initialize to an appropriate value
bool tru = true;
Isolate.WhenCalled(() => target.CheckUniqueness(entity, propertyNames, null, null)).WillReturn(tru);
target.ValidatePropertiesExist(entity, propertyNames);
Isolate.Verify.WasCalledWithArguments(() => target.ValidatePropertiesExist(entity, propertyNames));
Isolate.Verify.WasCalledWithArguments(() => target.CheckUniqueness(entity, propertyNames, null, null));
This throws an exception like "*** WhenCalled does not support using a method call as an argument."
Even though I'm able to do the same thing with a CLR class - I can mock out DateTime.Now doing this (code works):
DateTime endOfWorld = new DateTime(2012, 12, 23);
Isolate.WhenCalled(() => DateTime.Now).WillReturn(endOfWorld);
DateTime dt = DateTime.Now;
Assert.AreEqual(dt, endOfWorld);
Anyone have any advice here? Do I have to split these 2 methods into a seperate class and make an interface is the only way? or complicate my method/tests??? There must be something I'm missing here... Thanks much for any help in advance.
EDIT: I guess I'm trying to mock out the 2 private methods in the class for the one unit test. How could I do this without having to split out those 2 methods into a seperate class / interface?
try
Isolate.NonPublic.WhenCalled(object,"nonpublic method").IgnoreCall
or Isolate.Verify.NonPublic.WasCalled(object,"method"..
RhinoMocks has the AssertWasCalled method which may serve the purpose of guaranteeing that a method calls another method... but I'm not sure you can do that on a private function of the same class you are unit testing. I think you could only do that if the two methods you wanted to stub were in another dependency class that was injected.

Categories

Resources