I am trying to implement an unit test for a method in my class. How could I mock a base class indexer on the class method I am testing? Below code snippet should give a clear picture of my requirement.
public class MyClass:MyBase
{
public string returnString(string str1)
{
var xyz=base[str1];
//My code to unit test is here
}
}
public class MyBase
{
public virtual string this[string str1]
{
return "prefix"+str1;
}
}
I would like to stub my base class indexer with a dummy string and test my actual code. How can I do that?
Thanks for any help on this in advance.
Sree.
Normally not recommended practice, but in this case "appropriate": mock your class under test. Of course in this case, you'd only mock out stuff that's specific to the base class and not overridden in any way your descendant under test. This ensures that the base class' behavior is mocked and therefore under control of the tests when testing the descendant's methods.
In your example, you would create a mock of MyClass but only mock out the inherited (MyBase's) constructor, thus making sure that all other methods run "as coded", and then assert against the mocked instance.
I don't see the reason to stub your base class, since you can mock your class under test. I'll show you.
I added return statement to returnString() method, just for assertion to complete the test:
public string returnString (string str1)
{
var xyz = base [str1];
return xyz;
}
And now the test:
[TestMethod, Isolated]
public void TestIndexerFake()
{
//Arrange
var MyClassFake = Isolate.Fake.AllInstances<MyClass>(Members.CallOriginal);
Isolate.WhenCalled(() => MyClassFake["test"]).WillReturn("fake!");
//Act
MyClass target = new MyClass();
var result = target.returnString("test");
//Assert
Assert.AreEqual("fake!", result);
}
I'm using Typemock Isolator and MsTest.
Hope it helps!
Related
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);
Need to implement Moq Unit Test and Actual Unit Test in same test class , with help of some config file key.
Is it possible to do so using same object which will be assigned based on the config value ?
Means if config file key is "Moq" then Moq Unit Test will run and if not Actual Unit Test will run in same test class and in same method .
Yes you can, but likely it's not the best practice.
For example,
public class MyClass
{
IDependency _d;
public MyClass(IDependency d)
{
_d = d;
}
}
public class Dependency : IDependency
{
}
In the test class, I can have something like this:
[TestClass]
public class MyClassTests
{
MyClass _sut;
Mock<IDependency> _mockDependency;
Dependency _realDependency;
[TestInit]
public void Init()
{
var shouldUseMock = ConfigurationManager.AppSettings["key"];
if(shouldUseMock)
{
_mockDependency = new Mock<IDependency>();
_sut = new MyClass(_mockDependency.Object)
}
else
{
_realDependency = new Dependency();
_sut = new MyClass(_realDependency);
}
}
}
The problem will be setting up expectations based on different situations and it makes the test class much harder to maintain. You should rather create two tests, one real unit test with the mock and the other kind of integration test with real implementation.
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();
I currently have a base service class that all my services extend. This is what one of the methods look like:
protected internal virtual T PerformServiceOperationWithExceptionHandling<T>(Func<T> func)
{
try
{
return func.Invoke();
}
...
}
In the derived classes I call the method like this:
public AddGuestResponse AddGuest(AddGuestRequest addGuestRequest)
{
return PerformServiceOperationWithExceptionHandling(() => AddGuestLogic(addGuestRequest));
}
I want to test AddGuest and ensure "AddGuestLogic" is being passed as a parameter in the base method? How do I achieve this with nSubstitute and nUnit. I don't think its possible?
================================================
I ended up using the following code:
[Test]
public void AddGuest_WhenCalled_PerformsAddGuestLogicWithExceptionHandling()
{
Func<AddGuestResponse> addGuestLogic = null;
_guestService.PerformServiceOperationWithExceptionHandling(Arg.Do<Func<AddGuestResponse>>(arg => addGuestLogic = arg));
var addGuestRequest = new AddGuestRequest();
_guestService.AddGuest(addGuestRequest);
_guestService.ClearReceivedCalls();
addGuestLogic.Invoke();
_guestService.Received().AddGuestLogic(addGuestRequest);
}
The _guestService is created in my setup method as follows: Substitute.ForPartsOf();
I second Sunny Milenov's answer, but would go one step further by advising you to change your design. I have learned the hard way that many of these headaches with testing base class behavior go away when you follow the principle of composition over inheritance.
I.e., if you refactor your base class to a collaborator, which you inject into your services' constructor, you can test that in isolation and mock it in your services' tests. No worrying about testing an abstract base class or testing the same exception handling in all of your services' tests.
You would test that the collaborator correctly invokes the func in the collaborator's tests.
In the services' tests you can just mock the collaborator to return the Func's result right away:
[Test]
public void ServiceLogicIsExecuted()
{
var collaborator = Substitute.For<ICollaborator>();
//Tell the test double to return the Func's result. You'd probably want to do this in the setup method.
collaborator.PerformServiceOperation(Arg.Any<Func<int>>()).Returns(x => ((Func<int>)x[0]).Invoke());
var sut = new Service(collaborator);
var result = sut.CalculateSomething();
Assert.That(result, Is.EqualTo(99));
}
public class Service
{
private readonly ICollaborator _collaborator;
public Service(ICollaborator collaborator)
{
_collaborator = collaborator;
}
public int CalculateSomething()
{
return _collaborator.PerformServiceOperation(ExecuteLogic);
}
private static int ExecuteLogic()
{
return 99;
}
}
public interface ICollaborator
{
T PerformServiceOperation<T>(Func<T> func);
}
Short answer - you shouldn't. Unit testing is about testing the behavior of the tested method, not the implementation details.
Long answer:
It doesn't matter how the class internally works, as far as it produces the expected results.
You need to test your public method on the final class and see if this works as expected. Testing a base/abstract class in isolation proves nothing.
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();
}