Suppose I have the following class:
public class TestBase
{
public bool runMethod1 { get; set; }
public void BaseMethod()
{
if (runMethod1)
ChildMethod1();
else
ChildMethod2();
}
protected abstract void ChildMethod1();
protected abstract void ChildMethod2();
}
I also have the class
public class ChildTest : TestBase
{
protected override void ChildMethod1()
{
//do something
}
protected override void ChildMethod2()
{
//do something completely different
}
}
I'm using Moq, and I'd like to write a test that verifies ChildMethod1() is being called when I call BaseMethod() and runMethod1 is true. Is it possible to create an implemention of TestBase with Moq, call BaseMethod() and verify that ChildMethod was called on the Moq implementation?
[Test]
public BaseMethod_should_call_correct_child_method()
{
TestBase testBase;
//todo: get a mock of TestBase into testBase variable
testBase.runMethod1 = true;
testBase.BaseMethod();
//todo: verify that ChildMethod1() was called
}
You can also set the expectation/setup as Verifiable and do without a strict mock:
//expect that ChildMethod1() will be called once. (it's protected)
testBaseMock.Protected().Expect("ChildMethod1")
.AtMostOnce()
.Verifiable();
...
//make sure the method was called
testBase.Verify();
Edit
This syntax does not work in current versions of Moq. See this question for how to do it as of at least 4.0.10827
I figured out how to do this. You can can mock protected methods with Moq, and by making a strict mock, you can verify that they were called. Now I can test the base class without having to make any subclasses.
[Test]
public BaseMethod_should_call_correct_child_method()
{
//strict mocks will make sure all expectations are met
var testBaseMock = new Mock<TestBase>(MockBehavior.Strict);
//expect that ChildMethod1() will be called once. (it's protected)
testBaseMock.Protected().Expect("ChildMethod1")
.AtMostOnce();
var testBase = testBaseMock.Object;
testBase.runMethod1 = true;
testBase.BaseMethod();
//make sure the method was called
testBase.VerifyAll();
}
It's a bit of a hack, but how about creating a subclass of TestBase that makes ChildMethod1 and ChildMethod public and then Moqing that?
It seems like your testing the behaviour rather than the public interface. If this is intended then you could probably look at advice for testing private members.
"Is it possible to create an implemention of TestBase with Moq, call BaseMethod() and verify that ChildMethod was called on the Moq implementation?"
It's sort of possible. But then you would be testing the mock object, not the real object.
Two questions that might steer you in the right direction:
Does the descendatn class return a different value than the base class? If so you can test for that and ignore implimentation details (makes refactoring alot easier too).
Does the descendant class call different methods or different dependencies? If so you can check the dependencies.
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 an inheritance hierachy that looks something like this;
public abstract class SomeBaseClass
{
public virtual void DoSomething()
{
Console.WriteLine("Don't want this to run");
}
}
public class ConcreteImplementation1 : SomeBaseClass
{
}
public class ConcreteImplementation2 : ConcreteImplementation1
{
public override void DoSomething()
{
Console.WriteLine("This should run");
base.DoSomething();
}
}
Using NSubstitute I would like to stub ConcreteImplementation1's DoSomething() so that only the code in ConcreteImplementation2's DoSomething() method runs with the call to base.DoSomething() doing nothing.
Is this possible and if so how would I do this? Would the code look any different if DoSomething() were async?
Thanks
I don't think this is possible with NSubstitute, or with .NET in general. NSubstitute does support partial mocks, but this is on a per-member basis.
So you can make it call ConcreteImplementation2.DoSomething, but that implementation calls base.DoSomething so that will execute:
var sub = Substitute.For<ConcreteImplementation2>();
sub.When(x => x.DoSomething()).CallBase();
NSubstitute works by implementing/sub-classing a type, so a good rule of thumb is that if you can't do something manually by sub-classing, NSubstitute will not be able to do it either.
In this case, if you create a class ConcreteImplementation3 : ConcreteImplementation2 and override DoSomething, can you call ConcreteImplementation2.DoSomething without it calling SomeBaseClass.DoSomething? In this case I think the answer is no, so NSubstitute will not be able to do this either.
I have a base class:
public abstract class MyBaseClass
{
protected virtual void Method1()
{
}
}
and a derived class:
public class MyDerivedClass : MyBaseClass
{
public void Method2()
{
base.Method1();
}
}
I want to write a unit test for Method2 to verify that it calls Method1 on the base class. I'm using Moq as my mocking library. Is this possible?
I came across a related SO link:
Mocking a base class method call with Moq
in which the 2nd answer suggests it can be achieved by setting CallBase property to true on the mock object. However it's not clear how this would enable the call to the base class method (Method1 in the above example) to be verified.
Appreciate any assistance with this.
Unit tests should verify behavior, not implementation. There are several reasons for this:
The results are the goal, not how you get the results
Testing results allows you to improve the implementation without re-writing your tests
Implementations are harder to mock
You might be able to put in hooks or create mocks that verify that the base method was called, but do you really care how the answer was achieved, or do you care that the answer is right?
If the particular implementation you require has side effects that you can verify, then that is what you should be validating.
Mocking the base class from the perspective of the derived class is not possible. In your simple example, I would suggest one of the two options.
Option 1: In the event that MyDerivedClass really shouldn't care what MyBaseClass is up to, then use dependency injection! Yay abstraction!
public class MyClass
{
private readonly IUsedToBeBaseClass myDependency;
public MyClass(IUsedToBeBaseClass myDependency){
_myDependency = myDependency;
}
public void Method2()
{
_myDependency.Method1();
}
}
Elsewhere in test land...
[TestClass]
public class TestMyDependency {
[TestMethod]
public void TestThatMyDependencyIsCalled() {
var dependency = new Mock<IUsedToBeBaseClass>();
var unitUnderTest = new MyClass(dependency.Object);
var unitUnderTest.Method2();
dependency.Verify(x => x.Method1(), Times.Once);
}
}
Option 2: In the event that MyDerivedClass NEEDS to know what MyBaseClass is doing, then test that MyBaseClass is doing the right thing.
In alternative test land...
[TestClass]
public class TestMyDependency {
[TestMethod]
public void TestThatMyDependencyIsCalled() {
var unitUnderTest = new MyDerivedClass();
var unitUnderTest.Method2();
/* verify base class behavior #1 inside Method1() */
/* verify base class behavior #2 inside Method1() */
/* ... */
}
}
What you're describing is not a test of your code, but a test of the behavior of the language. That's fine, because it's a good way to ensure that the language behaves the way we think it does. I used to write lots of little console apps when I was learning. I wish I'd known about unit testing then because it's a better way to go about it.
But once you've tested it and confirmed that the language behaves the way you expect, I wouldn't keep writing tests for that. You can just test the behavior of your code.
Here's a real simple example:
public class TheBaseClass
{
public readonly List<string> Output = new List<string>();
public virtual void WriteToOutput()
{
Output.Add("TheBaseClass");
}
}
public class TheDerivedClass : TheBaseClass
{
public override void WriteToOutput()
{
Output.Add("TheDerivedClass");
base.WriteToOutput();
}
}
Unit test
[TestMethod]
public void EnsureDerivedClassCallsBaseClass()
{
var testSubject = new TheDerivedClass();
testSubject.WriteToOutput();
Assert.IsTrue(testSubject.Output.Contains("TheBaseClass"));
}
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.