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();
Related
I am trying to unit test code that uses an API, so I am trying to decouple.
I have created an interface for the "Application" class inside the API, which is sealed.
I then created a class that uses the interface which has one method that returns an "Application" type object.
Here is where I am having trouble, in my unit test I try to create an "Application" object to verify if the return value is correct. However the "Application" class does not have any constructors, nothing public or private(I checked with reflection). The object is created by calling static Application.Connect(AnotherTypeFromAPI arg), which returns an Application object.
How do I return a fake object that I cannot create?
appMock.Connect(arg).Returns("How do I return an Application object here?"));
Or am I going about this the wrong way in regards to unit testing code that relies on an API? The entire API relies on the "Application" type so if I cannot fake it, I am not sure yet how I can stub or mock the other methods I need.
I am using C#, NUnit, NSUbstitute.
This problem can be solved but you're using the wrong pattern. Instead of exposing an instance of the Application via a new interface, you need to create an interface that fully replaces the concrete dependency.
What you have
If I understand your question correctly, you have a sealed Application class that has some methods your program needs to be able to call, and it has no public constructor, only a static factory method. Here is a simple example for discussion, with only one method, SomeMethod().
public sealed class Application
{
//private ctor prevents anyone from using new to create this
private Application()
{
}
//Here's the method we want to mock
public void SomeMethod(string input)
{
//Implementation that needs to be stubbed or mocked away for testing purposes
}
//Static factory method
static public Application GetInstance()
{
return new Application();
}
}
What you tried
What you did might look like this:
interface IApplication
{
Application Application { get; }
}
class ApplicationWrapper : IApplication
{
protected readonly Application _application;
public ApplicationWrapper()
{
_application = Application.GetInstance();
}
public Application Application
{
get { return _application; }
}
}
So that in your main code, you do this:
var a = new ApplicationWrapper();
a.Application.SomeMethod("Real argument");
That approach will never work for unit testing, because you still have a direct dependency on the sealed Application class. You've just moved it. You still need to call Application.SomeMethod(), which is a concrete method; you are supposed to depend only on the interface, not anything concrete.
What would work
In theory, the "right" way to do this is to wrap everything. So instead of exposing Application as a property, you keep it private; instead, you expose wrapped versions of the methods, like this:
public interface IApplication
{
void SomeMethod(string input);
}
public class ApplicationWrapper : IApplication
{
protected readonly Application _application;
public ApplicationWrapper()
{
_application = Application.GetInstance();
}
public void SomeMethod(string input)
{
_application.SomeMethod(input);
}
}
Then you'd call it like this:
var a = new ApplicationWrapper();
a.SomeMethod("Real argument");
Or in a full class with DI, it would look like this:
class ClassUnderTest
{
protected readonly IApplication _application; //Injected
public ClassUnderTest(IApplication application)
{
_application = application; //constructor injection
}
public void MethodUnderTest()
{
_application.SomeMethod("Real argument");
}
}
How to unit test
In your unit test, you can now mock the IApplication with a new class, e.g.
class ApplicationStub : IApplication
{
public string TestResult { get; set; } //Doesn't exist in system under test
public void SomeMethod(string input)
{
this.TestResult = input;
}
}
Notice this class has absolutely no dependency on Application. So you no longer need to call new on it, or call its factory method, at all. For unit testing purposed, you just need to ensure it gets called properly. You can do this by passing in the stub and checking the TestResult afterward:
//Arrange
var stub = new ApplicationStub();
var c = ClassUnderTest(stub);
//Act
c.MethodUnderTest("Test Argument");
//Assert
Assert.AreEqual(stub.TestResult, "Test Argument");
It's a bit more work to write the full wrapper (especially if it has a lot of methods), but you can generate a lot of that code with reflection or with third party tools. And it allows you full unit testing, which is the whole idea behind switching to that IApplication interface to begin with.
TLDR:
Instead of
IApplication wrapper = new ApplicationWrapper();
wrapper.Application.SomeMethod();
you should use
IApplication wrapper = new ApplicationWrapper();
wrapper.SomeMethod();
to remove the dependency on the concrete type.
You don't normally mock or fake static methods such as Application.Connect. Just partition the code under test so that it takes an already created IApplication object.
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);
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!
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.
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.