Does the methods in mocked objects work ?
For example if I have an object with method name Method1 and I mock the object :
var mockobject= Mock<myobject>();
Does the next call to method work :
mockobject.Method1()
?
It is a question to clarify about the mock objects.
If you're mocking a concrete class or abstract class with method implementations. For virtual methods you have two options.
Create a Setup to fake the method call
mockobject.Setup(x => x.Method1()).Returns(true);
Set CallBase = true on the mock to invoke the concrete behavior of the Method1 method.
mockobject.CallBase = true;
Usage:
public class MyClass
{
public virtual int MyMethod()
{
return 5;
}
}
[Test]
public void ShouldGiveMeZero()
{
var mockMyClass = new Mock<MyClass>();
// returns default(int)
Assert.AreEqual(0, mockMyClass.Object.MyMethod());
}
[Test]
public void ShouldGiveMeFive()
{
var mockMyClass = new Mock<MyClass>();
mockMyClass.CallBase = true;
// calls concrete implementation
Assert.AreEqual(5, mockMyClass.Object.MyMethod());
}
[Test]
public void ShouldGiveMeSix()
{
var mockMyClass = new Mock<MyClass>();
mockMyClass.Setup(x => x.MyMethod()).Returns(6);
// calls Setup
Assert.AreEqual(6, mockMyClass.Object.MyMethod());
}
First, note that your example will never compile:
mockobject.Method1()
Method1 doesn't live on the mock object itself--it lives in the underlying mocked object instance:
mockobject.Object.Method1();
The behavior of that call depends on what MockBehavior you're using (Strict or Loose). It also depends on if the method you're calling is marked virtual or not.
If Method1 is non-virtual, the implementation for the actual type will be used, since Mock cannot mock non-virtual methods.
For example, if MyObject is defined like this:
public class MyObject
{
public int Method1()
{
return 1;
}
}
mockObject.Object.Method1() will return 1 since Mock is unable to provide any other implementation for the method.
Now, if Method1 is declared virtual:
public virtual int Method1()
{
return 1;
}
The MockBehavior comes into play. The default is MockBehavior.Loose, which means that methods not defined using the .Setup method will return default(T) where T is the return type of the method. So the following:
var mockObject = new Mock<MyObject>(MockBehavior.Default);
int result = mockObject.Object.Method1();
Will always return 0 unless you use .Setup to make it return otherwise. You can also specify CallBase = true on the Mock<MyObject> instance and the base implementation will be invoked for methods that aren't defined using .Setup.
If you're using MockBehavior.Strict, unimplemented methods will throw an exception:
var mockObject = new Mock<MyObject>(MockBehavior.Strict);
int result = mockObject.Object.Method1(); // Always throws an exception
If you look at the quickstart guide there are simple examples to get you going, e.g.
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
Note the call to Setup to make the mock/fake actually do something.
In this situation you have created the default stub for Method1. If you were to create this by hand you would have code similar to:
public class MyObject {
public virtual void Method1() {
throw new NotImplementedException();
}
}
Your stub would be:
public class Stub : MyObject {
public override void Method1() {
}
}
So now instead of getting a NotImplementedException you have an instance of MyObject that will allow you to call Method1 regardless of its original implementation.
Note my usage of virtual. Without the usage of virtual there is nothing for Moq to override.
This is actually one of my favorite usages of mocking. Many people go overboard with interfaces for everything "for mocking". The most baseline scenarios only require methods to be virtual. In general I mark nearly every public method I create as virtual. If a public method cannot be virtual, it is likely a violation of the Open Closed Principle.
Related
I have a test which mocks a non-interface object with a constructor that takes parameters:
[Test]
public void Test()
{
var myObject = Substitute.For<MyObject>("param1", "param2");
_sut.DoSomething(myObject);
myObject.Received().SomeMethodWhichIsCalled();
}
This passes and when I debug the test, I can see SomeMethodWhichIsCalled() on MyObject is executed correctly.
However I've now realised this assert does nothing, because I can add the below in:
[Test]
public void Test()
{
var myObject = Substitute.For<MyObject>("param1", "param2");
_sut.DoSomething(myObject);
myObject.DidNotReceive().SomeMethodWhichIsCalled();
myObject.Received().SomeMethodWhichIsCalled();
}
And the test still passes...
Is this a side effect of mocking classes and not interfaces?
You can mock only virtual members. The mocking-framework simply overrides the virtual members for you similar to this:
class MyMock : MyObject
{
override void SomeMethodWhichIsCalled()
{
throw new Exception("Method was called");
}
}
As your method is not virtual the framework isn´t able to override it and thus the actual method SomeMethodWhichIsCalled of MyObject is called, which never throws the exception.
There´s not much you can do about this, unless you can make the method virtual. You could try to access some internal state via reflection, but that highly depends on what SomeMethodWhichIsCalled does. In particular it´s only a dirty hack.
It is my understanding that I can test that a method call will occur if I call a higher level method, i.e.:
public abstract class SomeClass()
{
public void SomeMehod()
{
SomeOtherMethod();
}
internal abstract void SomeOtherMethod();
}
I want to test that if I call SomeMethod() then I expect that SomeOtherMethod() will be called.
Am I right in thinking this sort of test is available in a mocking framework?
You can see if a method in something you have mocked has been called by using Verify, e.g.:
static void Main(string[] args)
{
Mock<ITest> mock = new Mock<ITest>();
ClassBeingTested testedClass = new ClassBeingTested();
testedClass.WorkMethod(mock.Object);
mock.Verify(m => m.MethodToCheckIfCalled());
}
class ClassBeingTested
{
public void WorkMethod(ITest test)
{
//test.MethodToCheckIfCalled();
}
}
public interface ITest
{
void MethodToCheckIfCalled();
}
If the line is left commented it will throw a MockException when you call Verify. If it is uncommented it will pass.
No, mock testing assumes you are using certain testable design patterns, one of which is injection. In your case you would be testing SomeClass.SomeMethod and SomeOtherMethod must be implemented in another entity which needs to be interfaced.
Your Someclass constructor would look like New(ISomeOtherClass). Then you would mock the ISomeOtherClass and set expectation on its SomeOtherMethod to be called and verify the expectation.
Even though I agree that the #Paul's answer is the recommended way to go I just want to add one alternative way which is provided by moq off the self.
Since SomeClass is abstract it is indeed mockable, but public void SomeMehod() isn't. The point is to find the way to mock and somehow invoke that method and then using CallBase propagate the call to the SomeOtherMethod(). It might sound as a hack but it is simple in essence. It could be used in the case if the proposed refactoring is not possible.
// This class is used only for test and purpose is make SomeMethod mockable
public abstract class DummyClass : SomeClass
{
public virtual void DummyMethod() => base.SomeMethod();
}
Then you could setup DummyMethod() to propagate the call by setting CallBase flag.
//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();
//Act
mock.Object.SomeMethod();
//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);
Let's assume we have the following setup:
public interface IBase
{
void Foo();
}
public class Base : IBase
{
public virtual void Foo()
{
Console.WriteLine("Called Base.Foo()");
}
}
public interface IChild : IBase
{
void Bar();
}
public class Child : Base, IChild
{
public virtual void Bar()
{
Console.WriteLine("Called Child.Bar()");
}
}
When mocking the Child object everything works fine:
var child = new Mock<Child> { CallBase = true };
child.Object.Bar();
child.Object.Foo();
Output is:
Called Child.Bar()
Called Base.Foo()
But when mocking the IChild interface nothing is printed to the console:
var child = new Mock<IChild> { CallBase = true };
child.Object.Bar();
child.Object.Foo();
Let's assume I can't mock the Child object because there is no parameterless constructor (dependency injection).
I know that I could just do the following:
child.Setup(c => c.Bar()).Callback(() =>
{
// Copy paste bar-method body
});
child.Setup(c => c.Foo()).Callback(() =>
{
// Copy paste foo-method body
});
But that would be very ugly.
Is there a clean solution using Mock<IChild>?
As long as you are mocking the interface, you have no access or information about the real classes which explains why you don't get any output (but I guess you understood that).
Unfortunately if you choose to mock an interface (which by definition have no behavior), the only way to make things happen is to Setup the method the way you did.
Another "dirty" way would be to use method extension to your child and base class if the content of the method is only using public attributes and method.
public static class ChildExtension
{
public static void Bar(this Child child)
{
Console.WriteLine("Called Child.Bar()");
}
}
You are going to the wrong direction
Mock exists to help in unit testing. For example if you want to test the method Save() of a class which uses a wrapper over a DbContext like the following:
interface IRepository
{
void PersistData(object dataToBeSaved);
}
class DataSaver
{
private IRepository _repository;//this object's method PersistData makes a call to a database
public DataSaver(IRepository repository)
{
_repository = repository;
}
public void Save(object dataToBeSaved)
{
_repository.PersistData(dataToBeSaved);
}
}
In this case, in order to test the method Save of the DataSaver you will do a call to it in a unit test, but the problem you will face when doing this is that the method will actually try to save the data using the repository objet. Unless you send a fake repository your unit test will save data every time you run it, and this is not what a unit test should be doing. It should not run a method from a concrete IRepository object, but it should still call it's method.
What you could do in this case to avoid saving of an object is to make another class which implements IRepository only for testing:
class DummyRepository : IRepository
{
public object DataJustSaved { get; set; }
public void PersistData(object dataToBeSaved)
{
DataJustSaved = dataToBeSaved;
}
}
Now in your unit test you will do something like this:
var dummyRepository = new DummyRepository();
var dataSaver = new DataSaver(dummyRepository);
var savedObject = new Object();
var expectedObject = savedObject;
dataSaver.Save(savedObject);//test the save method
var actualObject = dummyRepository.DataJustSaved;
Assert.AreEqual(expectedObject, actualObject);//verify that the data was passed to the PersistData method
Here the Mock helps
It would be quite difficult to make a fake class for each unit test, that is what alternative mock offers:
var dummyRepository = new Mock<IRepository>();
var dataSaver = new DataSaver(dummyRepository.Object);
var savedObject = new Object();
dataSaver.Verify(x => x.PersistData(savedObject), Times.Once());// just make sure the method PersistData was invoked with the expected data and only once.
The reason Mock exists is to make pretty smart dummies for you, to write unit tests without a great impact but which can reveal bugs, and keep the code doing what only it's supposed to do.
In your case, if you really want to call the actual method of the concrete object:
child.Setup(c => c.Bar()).Callback(() =>
{
Console.WriteLine("Called Child.Bar()");
});
Then it means that you should not even try to use the mock to reproduce the exact same implementation of the object you mock. What would be the use of the mock if it is doing the same thing as the actual object?
In this case you should remove the mock and create a concrete Child object, as you do not want to simulate the behavior of a child, you are trying to achieve it using a mock which removes the functionality of the mock itself.
The simple answer is to use the concrete object in the unit test:
var child = new Child();
child.Bar();
child.Foo();
How do I replace a concrete class with its interface for the purpose of unit testing if I am using extension methods in that class?
I've got a method:
[HttpGet]
[Route("/yoyo/{yoyoId:int}/accounts")]
public ResponseYoyoEnvelope GetAccountsByYoyoId([FromBody] RequestYoyoEnvelope requestYoyoEnvelope, int yoyoId)
{
var responseYoyoEnvelope = requestYoyoEnvelope.ToResponseYoyoEnvelope();
// get our list of accounts
// responseEnvelope.Data = //list of accounts
return responseYoyoEnvelope;
}
I'd like to replace:
RequestYoyoEnvelope requestYoyoEnvelope
with an abstraction:
IRequestYoyoEnvelope requestYoyoEnvelope
however, ToResponseYoyoEnvelope is an extension method.
How do I replace a concrete class with its interface for the purpose of unit testing if I am using extension methods in that class?
You can write the extension method against the interface rather than the concrete class:
public static class Class2
{
public static void Extension(this ITestInterface test)
{
Console.Out.WriteLine("This is allowed");
}
}
Then you can do:
// "Test" is some class that implements the ITestInterface interface
ITestInterface useExtensionMethod = new Test();
useExtensionMethod.Extension();
Note too that this'll still work even if useExtensionMethod isn't explicitly of type ITestInterface:
Test useExtensionMethod = new Test();
useExtensionMethod.Extension();
There's controversy about whether this represents a Decorator pattern but keep in mind at a minimum that the Extension method isn't literally a part of the interface itself - it's still a static method "under the hood," it's just that the compiler's allowing you the convenience of treating this like an instance method.
Assuming
public class RequestYoyoEnvelope : IRequestYoyoEnvelope { ... }
Your extension method would need to target the interface
public static ResponseYoyoEnvelope ToResponseYoyoEnvelope(this IRequestYoyoEnvelope target) { ... }
Keep the action as is because the model binder will have issues binding the interface.
In your unit test you pass a concrete implementation of RequestYoyoEnvelope and the updated extension method should be able to be tested.
From your example you would not need an interface to test if that method is the method under test. just new up an instance of the model and pass it to the method during the unit test.
[TestMethod]
public void GetAccountsByYoyoIdTest() {
//Arrange
var controller = new YoyoController();
var yoyoId = 123456;
var model = new RequestYoyoEnvelope {
//you populate properties for test
};
//Act
var result = controller.GetAccountsByYoyoId(model, yoyoId);
//Assert
//...do your assertions.
}
I am trying to test the logic from some existing classes. It is not possible to re-factor the classes at present as they are very complex and in production.
What I want to do is create a mock object and test a method that internally calls another method that is very hard to mock.
So I want to just set a behaviour for the secondary method call.
But when I setup the behaviour for the method, the code of the method is invoked and fails.
Am I missing something or is this just not possible to test without re-factoring the class?
I have tried all the different mock types (Strick,Stub,Dynamic,Partial ect.) but they all end up calling the method when I try to set up the behaviour.
using System;
using MbUnit.Framework;
using Rhino.Mocks;
namespace MMBusinessObjects.Tests
{
[TestFixture]
public class PartialMockExampleFixture
{
[Test]
public void Simple_Partial_Mock_Test()
{
const string param = "anything";
//setup mocks
MockRepository mocks = new MockRepository();
var mockTestClass = mocks.StrictMock<TestClass>();
//record beahviour *** actualy call into the real method stub ***
Expect.Call(mockTestClass.MethodToMock(param)).Return(true);
//never get to here
mocks.ReplayAll();
//this is what i want to test
Assert.IsTrue(mockTestClass.MethodIWantToTest(param));
}
public class TestClass
{
public bool MethodToMock(string param)
{
//some logic that is very hard to mock
throw new NotImplementedException();
}
public bool MethodIWantToTest(string param)
{
//this method calls the
if( MethodToMock(param) )
{
//some logic i want to test
}
return true;
}
}
}
}
MethodToMock is not virtual and therefore can't be mocked. What you want to do is possible with a partial mock (I've done it in cases similar to yours), but the method you want to mock out must be either part of an interface implementation or be marked virtual. Otherwise, you can't mock it with Rhino.Mocks.
I recommend not mocking methods in the class under test, but your situation may be unique in that you can't refactor the class to make it easier to test at present. You might try explicitly making a delegate to prevent the method from being invoked when setting up the call.
Expect.Call( delegate { mockTestClass.MethodToMock(param) } ).Return(true);
Or, switch to using the AAA syntax, omitting the deprecated constructs.
[Test]
public void Simple_Partial_Mock_Test()
{
const string param = "anything";
var mockTestClass = MockRepository.GenerateMock<TestClass>();
mockTestClass.Expect( m => m.MethodToMock(param) ).Return( true );
//this is what i want to test
Assert.IsTrue(mockTestClass.MethodIWantToTest(param));
mockTestClass.VerifyAllExpectations();
}