Doesn't being required to virtualize all property accessors you want to mock kind of defeat the purpose of mocking?
I mean, if I have to modify my object and virtualize every single accesor I want to mock, couldn't I just as well inherit my class and mock it myself?
Your question is very valid but if you think about it,there is no other way to mock a class. If you take an interface, it's just a contract so the mock framework can mock how ever you want it but if you take a class, it already has an implementation for it's members.
So the mock framework, in order to be able to mock the class members, has to inherit from the class and override the member's behavior as requested and for this purpose only virtual members will work.
For eg. if you have (I'm showing methods but the same is true for properties)
class Foo
{
public void Bar()
{
}
public virtual void virtualBar()
{
}
}
then the mock framework probably creates something like this to mock
public class MockFoo : Foo
{
public override void virtualBar()
{
// mockery action
}
public new void Bar()
{
// mockery action
}
}
Now when you have
Foo foo = GetMockObject(); // you get an instance of MockFoo
now when you call
foo.Bar();
you don't intend for it to call the actual implementation but since it's a non virtual member, it will call the Foo's Bar()
on the other hand, calling
foo.VirtualBar();
would call MockFoo's VirtualBar() as it's a virtual member which would have the behavior injected by the mock framework as requested.
Related
I have an interface which I am mocking with 'NSubstitute' which contains properties that return concreate classes, that is the return value is not an interface. e.g
public interface ISomething
{
SomeObj First { get; }
SomeObj Second { get; }
}
The 'SomeObj' concrete class has a default constructor but 'NSubstitute' always returns 'null' for these properties. The class itself is not under my control so I cannot simply make it derive from an interface.
Can 'NSubstitute' mock these type of properties? Or is there a way to override the behaviour? Otherwise I have to manually initialise the mock before the test and that can be a lot of code (even if its reused through a common method).
Perhaps there is a simpler solution that I have over-looked?
Classes will be auto-mocked if they have a default (parameterless) constructor and all its members are virtual (see the note in the intro of Auto and recursive mocks). The aim of this is to reduce the potential for unwanted (destructive?) side-effects if we are using a substitute and suddenly hit a non-virtual, unmocked code path that does bad stuff in an instance we thought was fake.
NSubstitute doesn't have a way override this behaviour. Instead, I'd recommend creating all your substitutes via your own factory method (e.g. a static Sub.For<T>(...) method in your test project) that uses NSubstitute to produce a substitute, then applies all the specific initialisation rules you need, like using reflection to stub out values for each class property.
Hope this helps.
Possibly related links:
I advise trying to avoid mocking types we don't own.
Stack Overflow: Is it recommended to mock concrete class?
Hacky factory method sample that subs properties using reflection.
It doesn't count as auto-mocking but you did also ask "Or is there a way to override the behaviour?" and "Perhaps there is a simpler solution that I have over-looked?"
This answer relies on the statements in your question that:
SomeObj is a class outside of your control, from which I assume it is either separately tested or else not testable
SomeObj has a default constructor
Sure, it requires you to "manually initialise the mock before the test" but since you've not told us what this object is it's not possible to know how much work it would take to implement fully.
public class SomeObj
{
// Non-virtual to prevent auto-mocking
public void Dummy() { }
}
public interface ISomething
{
SomeObj First { get; }
SomeObj Second { get; }
}
[TestMethod]
public void Test_17182355ms()
{
ISomething mockedSomething = Substitute.For<ISomething>();
SomeObj firstObj = mockedSomething.First;
Assert.IsNull(firstObj);
mockedSomething.First.Returns(new SomeObj());
mockedSomething.Second.Returns(new SomeObj());
firstObj = mockedSomething.First;
Assert.IsNotNull(firstObj);
}
Another approach, though not without its own drawbacks, would be to extract your own interface for SomeObj, something like this:
public interface ISomeObj
{
void Dummy();
}
public class MySomeObj : SomeObj, ISomeObj
{
}
and then mock ISomeObj in your test.
I have class that constructor calls a function in constructor. When I create mock for this class then function is called from constructor. I want to block function calling. Can I do it?
Sample code:
public class Foo
{
public Foo()
{
Initialize();
}
private void Initialize()
{
//some code
}
}
[TestFixture]
public class Test
{
[Test]
public void Test_Foo()
{
Foo foo = MockRepository.GenerateMock<Foo>();
//some test
}
}
Notes:
I don't want to add interface, like Foo : IFoo.
I don't want to add second constructor.
When you are mocking a class, there is proxy created (Rhino uses Castle.DynamicProxy.DefaultProxyBuilder), which inherits from your class. And inheritance works exactly like anywhere in C#. When you create instance of derived type, all constructors of base types (up to object) are invoked.
So, when instance of proxy is created (via Activator.CreateInstance(typeof(proxy))), constructor of Foo also will be invoked. You can't avoid this. You can use interface mocking, or provide some parameter to constructor which will disable initializing.
BTW mocking abstract or concrete class kills all advantages of mocks - your tests becomes dependent on something that is not mocked (constructors, non-virtual methods and default implementations). And your SUT (system under test) is not tested in isolation anymore. Broken test could be result of some changes inside abstract or concrete class.
In general you can create mocks of interfaces or abstract classes only.
What are you going to test? If it is the class Foo then creating a mock of it is completely wrong.
Usually you create mocks of those dependencincies of your tested class that are hard to set up or take long to run. Most common example of such dependency is a repository or a web-service.
How abt adding a Boolean flag
Boolean flag = false;
[Test]
public void Test_Foo()
{
if(flag == true)
{
Foo foo = MockRepository.GenerateMock<Foo>();
}
//some test
}
It came to my attention lately that you can unit test abstract base classes using Moq rather than creating a dummy class in test that implements the abstract base class. See How to use moq to test a concrete method in an abstract class? E.g. you can do:
public abstract class MyAbstractClass
{
public virtual void MyMethod()
{
// ...
}
}
[Test]
public void MyMethodTest()
{
// Arrange
Mock<MyAbstractClass> mock = new Mock<MyAbstractClass>() { CallBase = true };
// Act
mock.Object.MyMethod();
// Assert
// ...
}
Now I was wondering if there was a similar technique to allow me to test protected members without having to create a wrapper class. I.e. how do you test this method:
public class MyClassWithProtectedMethod
{
protected void MyProtectedMethod()
{
}
}
I'm aware of the Moq.Protected namespace, however as far as I can see it only allows you to setup expectations with e.g.
mock.Protected().Setup("MyProtectedMethod").Verifiable();
I'm also aware that the obvious answer here is "don't test protected methods, only test public methods", however that's another debate! I just want to know if this is possible using Moq.
Update: below is how I would test this normally:
public class MyClassWithProtectedMethodTester : MyClassWithProtectedMethod
{
public void MyProtectedMethod()
{
base.MyProtectedMethod();
}
}
Thanks in advance.
Another way in Moq to call protected member is the following template:
In your class, with protected member mark your function as virtual.
For example:
public class ClassProtected
{
public string CallingFunction(Customer customer)
{
var firstName = ProtectedFunction(customer.FirstName);
var lastName = ProtectedFunction(customer.LastName);
return string.Format("{0}, {1}", lastName, firstName);
}
protected virtual string ProtectedFunction(string value)
{
return value.Replace("SAP", string.Empty);
}
}
Then in your unit test add reference to
using Moq.Protected;
and in your unit test you can write the following:
[TestFixture]
public class TestClassProttected
{
[Test]
public void all_bad_words_should_be_scrubbed()
{
//Arrange
var mockCustomerNameFormatter = new Mock<ClassProtected>();
mockCustomerNameFormatter.Protected()
.Setup<string>("ProtectedFunction", ItExpr.IsAny<string>())
.Returns("here can be any value")
.Verifiable(); // you should call this function in any case. Without calling next Verify will not give you any benefit at all
//Act
mockCustomerNameFormatter.Object.CallingFunction(new Customer());
//Assert
mockCustomerNameFormatter.Verify();
}
}
Take note of ItExpr. It should be used instead of It. Another gotcha awaits you at Verifiable. I don't know why, but without calling to Verifiable Verify will not be called.
For starters, there's no point in unit testing an abstract method. There's no implementation! You may want to unit test an impure abstract class, verifying that the abstract method was called:
[Test]
public void Do_WhenCalled_CallsMyAbstractMethod()
{
var sutMock = new Mock<MyAbstractClass>() { CallBase = true };
sutMock.Object.Do();
sutMock.Verify(x => x.MyAbstractMethod());
}
public abstract class MyAbstractClass
{
public void Do()
{
MyAbstractMethod();
}
public abstract void MyAbstractMethod();
}
Note that I set CallBase to turn this into a partial mock, in case Do was virtual. Otherwise Moq would have replaced the implementation of the Do method.
Using Protected() you could verify that a protected method was called in a similar manner.
When you create a mock with Moq or another library, the whole point is overriding implementation. Testing a protected method involves exposing existing implementation. That's not what Moq is designed to do. Protected() just gives you access (presumably through reflection, since it's string-based) to override protected members.
Either write a test descendant class with a method that calls your protected method, or use reflection in the unit test to call the protected method.
Or, better yet, don't test protected methods directly.
You've already touched upon the "test the public API, not private" thought process, and you've also already mentioned the technique of inheriting from the class and then testing its protected members that way. Both of these are valid approaches.
Beneath it all, the simple truth is that you consider this implementation detail (as that's what a private or protected member is) important enough to test directly rather than indirectly via the public API that would use it. If it is this important, perhaps it's important enough to promote to its own class. (After all, if it's so important, perhaps it is a responsibility that MyAbstractClass should not have.) The instance of the class would be protected inside MyAbstractClass, so only the base and derived types would have access to the instance, but the class itself would be fully testable otherwise and usable elsewhere if that became a need.
abstract class MyAbstractClass
{
protected ImportantMethodDoer doer;
}
class ImportantMethodDoer
{
public void Do() { }
}
Otherwise, you're left* to the approaches you've already identified.
*Moq may or may not provide some mechanism for getting at private or protected members, I cannot say, as I do not use that particular tool. My answer is more from an architectural standpoint.
If I'm mocking a class, like below, is there any way I can get the mock to not override a virtual method? I know I can simply remove the virtual modifier, but I actually want to stub out behavior for this method later.
In other words, how can I get this test to pass, other than removing the virtual modifier:
namespace Sandbox {
public class classToMock {
public int IntProperty { get; set; }
public virtual void DoIt() {
IntProperty = 1;
}
}
public class Foo {
static void Main(string[] args) {
classToMock c = MockRepository.GenerateMock<classToMock>();
c.DoIt();
Assert.AreEqual(1, c.IntProperty);
Console.WriteLine("Pass");
}
}
}
You want to use a partial mock, which will only override the method when you create an expectation:
classToMock c = MockRepository.GeneratePartialMock<classToMock>();
c.DoIt();
Assert.AreEqual(1, c.IntProperty);
I see a couple of things here.
First, you are mocking a concrete class. In most/all cases, this is a bad idea, and usually indicates a flaw in your design (IMHO). If possible, extract an interface and mock that.
Second, although technically the mock is overriding the virtual method, it might be better to think of what it is doing is actually mocking/faking the method by providing an implementation (one that does nothing in this case). In general, when you mock an object, you need to provide the implementation for each property or method your test case requires of the object.
Update: also, I think removing "virtual" will prevent the framework from being able to do anything with the method.
Is there any way to have a mock constructed instead of a real instance when testing code that calls a constructor?
For example:
public class ClassToTest
{
public void MethodToTest()
{
MyObject foo = new MyObject();
Console.WriteLine(foo.ToString());
}
}
In this example, I need to create a unit test that confirms that calling MethodToTest on an instance of ClassToTest will indeed output whatever the result of the ToString() method of a newly created instance of MyObject.
I can't see a way of realistically testing the 'ClassToTest' class in isolation; testing this method would actually test the 'myObject.ToString()' method as well as the MethodToTest method.
Not really. Your ClassToTest is hard to test because of its design. If you want to be able to swap out its dependencies for mock objects, then you need to think about how these dependencies are injected - but just creating them in the constructor is not an approach that is going to help you. You could use constructor injection:
public class ClassToTest
{
MyObject _foo;
public void MethodToTest(Myobject foo)
{
_foo = foo;
Console.WriteLine(foo.ToString());
}
}
or you could use property injection:
public class ClassToTest
{
public MyObject Foo { get; set; }
public void MethodToTest()
{
}
}
The former may suit your example more given you want to write out the console there; it is often the best approach when your dependency is a must have dependency for the object rather than an optional one.
You could do a lot worse than exploring the concepts of dependency injection and inversion of control.