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.
Related
I am trying to unit test using Moq. Here is the example code:
public class ConcreteClass
{
private readonly FirstPropery firstProperty;
private readonly SecondProperty secondProperty;
public ConcreteClass(firstProperty, secondProperty)
{
this.firstProperty = firstProperty;
this.secondProperty = secondProperty;
}
}
[TestMethod]
var concreteClassMock = new Mock<ConcreteClass>() { CallBase = true };
In my test method, I want to set firstProperty to reference a real object FirstProperty object (created by a factory), and later use it to test another object's behavior. Is there any way to achieve that?
Usually, you wouldn’t mock private members since you are only mocking the public interface of something. A mock is thus completely independent of implementation details.
That being said, you can pass constructor arguments to the Mock constructor that will then be passed on to the target’s constructor:
new Mock<ConcreteClass>(firstProperty, secondProperty) {CallBase = true};
However, if your goal is to actually test the ConcreteClass, you should not create a mock of it. You should test the actual object. So mock its dependencies and pass those if necessary, but keep the object you want to test actually real. Otherwise, you might introduce and test behavior that comes from the mock instead of the object you are testing:
var firstMock = new Mock<FirstProperty>();
var secondMock = new Mock<FirstProperty>();
var obj = new ConcreteClass(firstMock.Object, secondMock.Object);
obj.DoSomething();
// assert stuff
A few remarks:
1- It could be easily achieve with an interface and a get method like this:
public interface IConcreteClass
{
FirstProperty FirstProperty { get; }
}
[Test]
public void TestCase()
{
var yourFirstPropertyImplementation = new FirstProperty();
var concreteClassMock = new Mock<IConcreteClass>();
concreteClassMock.Setup(o => o.FirstProperty).Returns(yourFirstPropertyImplementation);
}
2- Depending of your scenario, do you really need a Moq, why not just use the true implementation and use moq only at boundaries?
3- You should clarify what you want to test? If it's concrete class? or the properties? or some other classes? The test case I propose in 1 is valid only to test the interaction of concrete class with some other classes.
I've done extensive research on this topic and have yet to find a reliable answer so here goes.
I have a constructor I'd like to test. This constructor initializes another class in order to set a global variable which is necessary throughout the rest of the class. However, the constructor of the class which the constructor initializes has dependencies on things like web session and other variables being set which are not set when the any tests run. How can I properly mock this to make sure I'm just testing the constructor?
Here's the constructor to be tested:
public CheckoutManager()
{
_orderController = new OrderController();
_orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
The problem lies in the OrderController constructor:
public OrderController()
{
_customer = WebUserSession.Current.Profile.Customer;
_srd = ContextManager.GetStandardRequestByCulture( CultureInfo.CurrentUICulture.Name );
WarehouseData data = new WarehouseData();
data.WarehouseID = 0; // TODO: Convert the 0 warehouse to a web warehouse type
// Grab the attention items from the session
AttentionItems = WebUserSession.Current.OrderAttentionItems;
// Load the shopping cart
_cart = ShoppingCartManager.Cart;
}
Here is my attempted test:
[TestMethod]
public void Constructor_ExpectInstantiation()
{
var checkoutManager = new CheckoutManager();
Assert.IsNotNull( checkoutManager );
}
It bombs out at the _customer = WebUserSession.Current.Profile.Customer; line. How do you mock this using Moq? If it cannot be mocked, is there a good explanation as to why? How could the original constructor be modified to have the same functionality in a more testable way? Thank you in advance.
You can use Dependency Injection, which is a form of Inversion of Control, to solve these kind of problems.
Instead of instantiating your OrderController in the constructor, pass it as an argument:
public CheckoutManager(OrderController orderController)
{
_orderController = orderController;
_orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
You can then either instantiate the OrderController either manually somewhere in a Main-like method, or with a library like Autofac which will do all the wiring for you.
So now you can mock your interface in your test:
[TestMethod]
public void Constructor_ExpectInstantiation()
{
Mock<OrderController> mockOrderController = new Mock<OrderControler>();
var checkoutManager = new CheckoutManager(mockOrderController.Object);
Assert.IsNotNull( checkoutManager );
}
That way, the constructor of OrderController will never be called (it's a mock) and it won't interfere with your tests of CheckoutManager. If you need to test some interactions with it, you can Setup and Verify specific methods using Moq.
You won't be able to use Moq test to this code. You could
Modify the code to make it more testable by adding a constructor that accepts an OrderController
Use a more "advanced" testing technique such as shims.
I'm currently writing unit tests using Microsoft Fakes framework. I've noticed that if I don't supply a delegate for a given property, the default value is returned. However, when initializing my shim I change this behavior to NotImplemented.
var myShim = new ShimMyClass
{
InstanceBehavior = ShimBehaviors.NotImplemented
}
This is the given behavior I want for all my shims I define. I'd like to be able to set this default at a more global level, instead of having to remember to do it for every shim I create. Is this possible?
According to documentation, the following code snippet could help you:
using (ShimsContext.Create())
{
ShimBehaviors.Current = ShimBehaviors.NotImplemented;
var myShim = new ShimMyClass
{
...
}
}
However, it doesn't work on my machine with VS2012. Perhaps it is a bug.
Create a class that you will use as a superclass for all shims you write. In this class have a
protected static ShimBehavior Default = ShimBehavior.NotImplemented;
Then, make the constructor:
public ShimSuperClass
{
InstanceBehavior = Default
}
Just make sure to call the base() constructor in all of your subclasses
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>();
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.