Setting up Moq to ignore a virtual method - c#

I have an abstract class that has a virtual method. The method is virtual in the event that a later implementation needs to override that functionality.
However, Moq proxies all virtual methods so I don't seem to be able to test the actual code that's written, and instead uses the Mock setup for that method (which is currently to return the default value).
Example abstract:
public abstract SomeAbstract
{
public abstract Format(IFormatProvider provider, string format)
{
// does some stuff i need to test
}
}
My NUnit test:
[Test]
public void Should_Set_Format_State()
{
Mock<SomeAbstract> mock = new Mock<SomeAbstract>();
mock.Object.Format(CultureInfo.CurrentCulture, "format string");
// do tests to make sure Format correctly changed the object's state
}
How do I set up my Mock object to just let my virtual Format method work, without having to remove virtual from the method?! Perhaps I'm abusing the mocking concept in this case.

I believe setting "CallBase = true" on the mock will work. See the "Customizing Mock Behavior" section of the Quick Start

Related

Moq testing if method1 calls second method2 in same class

I'm new to Moq
I read a lot about Moq testing and that you shouldn't test your mock object, instead you should use Moq to stub dependencies and make it to act like you want to. But now I am asking myself, how can you test if a method be called from another method in the same class, like this code:
public class A // --> class i want to test
{
public virtual void TestMethod() // --> does it call testmethod2
{
TestMethod2();
}
public virtual void TestMethod2()
{
// Do something
}
}
I thought I can write the Unittest like this:
[TestMethod]
public void MyTestMethod()
{
Mock<A> aMock = new Mock<A>();
aMock.Verify(o => o.TestMethod2(), Times.Once);
aMock.TestMethod();
aMock.VerifyAll();
}
But is this valid? Thank you for all good answers!
Moq is only able to mock out methods which are virtual (or provide mock implementations for interfaces). If you try a Setup or Verify on a non-virtual member, you'll get the error
Invalid verify on a non-virtual member: m => m.TestMethod2()
In your case, you would need to change TestMethod2 to virtual, i.e.
public virtual void TestMethod2()
Which can then be tested:
var aMock = new Mock<A>();
aMock.Object.TestMethod();
aMock.Verify(m => m.TestMethod2(), Times.Once);
As you've suggested, testing whether a class calls methods internal to itself is a smell, indication that you're either
Testing internal implementation detail (e.g. if TestMethod2() was private, it's none of our business to even know about it).
Or, an indication that the Class / System under test is in need of refactoring into multiple classes, which should be loosely coupled, and hence can be isolated and better testable.
Note
You can't Verify a call before you've invoked the method on the SUT that you want to test, i.e. move the Verify to after the invocation of .TestMethod() as I've done.
Although you could change your code to use the Setup + VerifyAll approach to testing, i.e. ensuring that everything you've setup is actually invoked:
aMock.Setup(m => m.TestMethod2());
aMock.Object.TestMethod();
aMock.VerifyAll();
There is however debate around whether the usage of VerifyAll violates AAA principals (since you're also in effect specifying the Verify criteria in the Arrange piece), and I've also found that this approach makes it impossible to refactor and DRY up Mock setups in large scale tests, and you also lose some of the finer level of checking (e.g. Times.Once).

How to write unit test for private method in c# using moq framework?

I want to write unit test for private method in C# using moq framework, I've search in StackOverFlow and Google, but I cannot find the expected result. Please help me if you can.
You can't, at least not with Moq.
But more importantly, you shouldn't.
First off, you don't test methods, you test behaviours. Second, in order to test behaviours, you exercise a type's public API and verify the outcomes of that exercise.
Private methods are implementation details. You don't want to verify how things get done, you want to verify that things do get done.
In the AssemblyInfo.cs of your project add
[assembly: InternalsVisibleTo("Namespace.OfYourUnitTest.Project")]
then you make the method internal instead of private.
It has the benefit of avoiding to make it public.
However as pointed by dcastro, some people strongly disagree with this way of testing.
Perhaps you shouldn't (see other answers for why), but you can do this using Microsoft's Visual Studio Test Tools. A simplified example is given below.
Given the following class which you want to test:
public class ClassToTest
{
private int Duplicate(int n)
{
return n*2;
}
}
You can use the following code to test the private Duplicate method:
using Microsoft.VisualStudio.TestTools.UnitTesting;
// ...
[TestMethod]
public void MyTestMethod()
{
// Arrange
var testClass = new ClassToTest();
var privateObject = new PrivateObject(testClass);
// Act
var output = (int) privateObject.Invoke("Duplicate", 21);
// Assert
Assert.AreEqual(42, output);
}
Simply, you don't. Private methods are not visible to other classes.
There are a number of ways around this:
Treat the private as part of the method you're testing, cover it in their unit tests. Think of the public methods as black boxes and test their operations.
Make it protected and inherit your test class from the class you're testing (or use a partial - same idea)
Make it public (which if you're coding to an interface doesn't actually expose it to your consumers)
For public methods (option three) it is possible to partial mock the class where you can replace the method. In Moq you can do this like this:
var moq = new Mock<MyClass>();
moq.CallBase = true;
moq.Setup(x => x.MyPublicMethodToOverride()).Returns(true);
There are more details here.
Moq supports mocking protected methods. Changing the methods to protected, instead of private, would allow you to mock their implementation.
The following is from Moq Quickstart Documentation (deep link):
Setting expectations for protected members (you can't get IntelliSense
for these, so you access them using the member name as a string).
Assuming the following class with a protected function should be
mocked:
public class CommandBase {
protected virtual int Execute(); // (1)
protected virtual bool Execute(string arg); // (2)
}
// at the top of the test fixture
using Moq.Protected;
// In the test, mocking the `int Execute()` method (1)
var mock = new Mock<CommandBase>();
mock.Protected()
.Setup<int>("Execute")
.Returns(5);
// If you need argument matching, you MUST use ItExpr rather than It
// planning on improving this for vNext (see below for an alternative in Moq 4.8)
// Mocking the `bool Execute(string arg)` method (2)
mock.Protected()
.Setup<bool>("Execute",
ItExpr.IsAny<string>())
.Returns(true);
Moq 4.8 and later allows you to set up protected members through a
completely unrelated type that has the same members and thus provides
the type information necessary for IntelliSense to work. Pickin up the
example from the bullet point above, you can also use this interface
to set up protected generic methods and those having by-ref
parameters:
// Completely unrelated Interface (CommandBase is not derived from it) only created for the test.
// It contains a method with an identical method signature to the protected method in the actual class which should be mocked
interface CommandBaseProtectedMembers
{
bool Execute(string arg);
}
mock.Protected().As<CommandBaseProtectedMembers>()
.Setup(m => m.Execute(It.IsAny<string>())) // will set up CommandBase.Execute
.Returns(true);

Moq Assert an abstract method is called

I'm writing a unit test for my Abstract class using AutoFixture, this is a representation of what I'm trying to do:
public abstract class Base
{
public virtual void DoSomethingCool()
{
OnDoingSomethingCool();
}
protected abstract void OnDoingSomethingCool();
}
My unit test would look like this:
[TestMethod]
public void TestMethod1()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var sut = fixture.Create<Base>();
// How to assert that the OnDoingSomethingCool method was called
sut.Invoking(x => x.DoSomethingCool())
.ShouldNotThrow();
}
So how do I assert that the protected abstract method was actually called in the DoSomethingCool method??
If it were an object from an injected dependency, I would be able to setup a mock using Moq and assert that the method was called, but since the method is an abstract method inside my Subject Under Test, how do I assert the method was called?
There is a bunch that can be said about this:
It seems like you might be either testing too much, or giving too much control to other implementations.
(Too much control) Usually, if you want to force a method to be called from another method in your abstract class you do not make it public virtual. By doing this, you have given the future implementations the ability to change this behavior. In fact, if you remove the virtual, then you can get the test you want (see below). I did provide a way to keep the virtual, but again...not recommended. This is not recommended since your SUT is your mock...which doesn't feel right.
(Testing too much) You should only care about basic behavior, not implementation details, lest your tests become too brittle. I am assuming that there is more than just the call to the OnDoingSomethingCool method, otherwise you should just make that your main method. If the primary behavior is this call (and there is more than just this call), then I do cover that in my NotRecommended method below.
You should not test the abstract class directly. You should probably use what Roy Osherove calls the Abstract Test Class Pattern in The Art of Unit Testing. This makes it so that all implementations test your behavior. You can then pass in a dependency. If you would like that example or even a simplified example off the Abstract Test Class Pattern, let me know
/
using Moq.Protected;
...
public void NotRecommended_ProbablyTestingTooMuch_BrittleTestBelow
{
//If you MUST keep DoSomethingCool virtual
//var baseMock = new Mock<Base>{CallBase = true};
var baseMock = new Mock<Base>();
baseMock.Protected().Setup("OnDoingSomethingCool");
baseMock.Object.DoSomethingCool();
baseMock.Protected().Verify("OnDoingSomethingCool", Times.AtLeastOnce());
}

how can protected members of base class be accessed during unit test?

I am creating a unit test in mstest with rhino mocks. I have a class A that inherits class B. I am testing class A and create an instance of it for my test. The class it inherits, "B", has some protected methods and protected properties that I would like to access for the benefit of my tests. For example, validate that a protected property on my base class has the expected value.
Any ideas how I might access these protected properties of class B during my test?
This is wrong approach from unit testing perspectives. You should test only public interface and ensure that it behaves as expected, you should not care details of implementation like private/protected. So there are either:
methods/properties you are going to test really should be public OR
your test case/particular test implementation is wrong
EDIT:
Sometimes when writing unit tests for legacy code which you not able to change you could be forced to access protected members, in this case solution could be creating a wrapper which exposes internal/public property/method to access protected one.
Also what interesting, you marked question by TDD tag, try out imagine how you would be able accessing details of implementation in unit tests when you do not have an implementation yet? This is how TDD works - you have an interfaces and start writing unit tests before an implementation done.
Besides that the other answers point into the right direction, if you really need to test like you described, do this:
Create a class TestA that inherits from A. Use this to make the protected properties of B public for the test. If you have
class B {
protected string Name {get; set;}
}
class A: B {
public void DoSomething(string msg) {
Name = msg.Trim();
}
}
class TestA: A {
public string GetName() {
return Name;
}
}
In your test, now use TestA. I don't know MsTest syntax, but roughly it is this:
[Test]
public void TestThatNameWasSet() {
TestA systemUnderTest = new TestA();
systemUnderTest.DoSomething(" new name ");
Assert.That(systemUnderTest.GetName(), Is.EqualTo("new name");
}
Your protected properties should affect some aspect of the public behaviour of your class.
Test this public behaviour.
As far as your tests are concerned the internal workings of the class should be a black box. This will give you the freedom to refactor without having to mess with your tests. The only important thing is what public stuff they expose and this is what should be tested.

Verifying a method was called

Using Moq, I have a very odd issue where the setup on a mock only seems to work if the method I am setting up is public. I don't know if this is a Moq bug or if I just have this wrong (newbie to Moq). Here is the test case:
public class TestClass
{
public string Say()
{
return Hello();
}
internal virtual string Hello()
{
return "";
}
}
[TestMethod]
public void Say_WhenPublic_CallsHello()
{
Mock<TestClass> mock = new Mock<TestClass>();
mock.Setup(x => x.Hello()).Returns("Hello World");
string result = mock.Object.Say();
mock.Verify(x => x.Hello(), Times.Exactly(1));
Assert.AreEqual("Hello World", result);
}
Which fails with this message:
Say_WhenPublic_CallsHello failed: Moq.MockException:
Invocation was not performed on the mock 1 times: x => x.Hello()
at Moq.Mock.ThrowVerifyException(IProxyCall expected, Expression expression, Times times)...
If I make the Hello method public like this, the test passes. What is the issue here?
public virtual string Hello()
{
return "";
}
Thanks in advance!
The test fails when Hello() is internal because Moq cannot provide an override of the method in this case. This means that the internal implementation of Hello() will run, rather than mock's version, causing the Verify() to fail.
Incidentally, what you are doing here makes no sense in the context of a unit test. A unit test should not care that Say() calls an internal Hello() method. This is implementation internal to your assembly and not a concern of consuming code.
I don't know enough about how this works underneath the covers to give you a technical answer as to exactly why that is the behaviour, but I think I can help with your confusion.
In your example you are calling a method Say(), and it is returning the expected text. Your expectation should not enforce a particular implementation of Say() ie that it calls an internal method called Hello() to return that string. This is why it does not pass the verify, and also why the string returned is "", ie the actual implementation of Hello() has been called.
By making the Hello method public it appears that this has enabled Moq to intercept the call to it, and use it's implementation instead. Therefore, in this case the test appears to pass. However, in this scenario you haven't really achieved anything useful, because your test says that when you call Say() the result is "Hello World" when in acutal fact the result is "".
I have rewritten your example to show how I would expect Moq to be used (not necessarily definitive, but hopefully clear.
public interface IHelloProvider
{
string Hello();
}
public class TestClass
{
private readonly IHelloProvider _provider;
public TestClass(IHelloProvider provider)
{
_provider = provider;
}
public string Say()
{
return _provider.Hello();
}
}
[TestMethod]
public void WhenSayCallsHelloProviderAndReturnsResult()
{
//Given
Mock<IHelloProvider> mock = new Mock<IHelloProvider>();
TestClass concrete = new TestClass(mock.Object);
//Expect
mock.Setup(x => x.Hello()).Returns("Hello World");
//When
string result = concrete.Say();
//Then
mock.Verify(x => x.Hello(), Times.Exactly(1));
Assert.AreEqual("Hello World", result);
}
In my example, I have introduced an interface to an IHelloProvider. You will notice that there is no implementation of IHelloProvider. This is at the heart of what we are trying to achieve by using a mocking solution.
We are trying to test a class (TestClass), which is dependant on something external (IHelloProvider). If you are using Test Driven Development then you probably haven't written an IHelloProvider yet, but you are aware that you will need one at some point. You want to get TestClass working first though, rather than get distracted. Or perhaps IHelloProvider uses a database, or a flat file, or is difficult to configure.
Even if you have a fully working IHelloProvider, you are still only trying to test the behaviour of TestClass, so using a concrete HelloProvider is likely to make your test more prone to failure, for instance if there is a change to the behaviour of HelloProvider, you don't want to have to change the tests of every class that uses it, you just want to change the HelloProvider tests.
Getting back to the code, we now have a class TestClass, which is dependant on an interface IHelloProvider, the implementation of which is provided at construction time (this is dependency injection).
The behaviour of Say() is that it calls the method Hello() on the IHelloProvider.
If you look back at the test, we have created an actual TestClass object, since we actually want to test the code that we have written. We have created a Mock IHelloProvider, and said that we expect it to have it's Hello() method called, and when it does to return the string "Hello World".
We then call Say(), and verify the results as before.
The important thing to realise is that we are not interested in the behaviour of the IHelloProvider, and so we can mock it to make testing easier. We are interested in the behaviour of TestClass, so we have created an actual TestClass not a Mock, so that we can test it's actual behaviour.
I hope this has helped to clarify what is going on.
Moq doesn't do partial mocking and can only mock public virtual methods or interfaces. When you create a Mock you are creating a completely new T and removing all implementation of any public virtual methods.
My suggestion would be to concentrate on testing the public surface area of your objects and not their internals. Your internals will get coverage. Just make sure you have a clear idea of what your target class is and don't mock that (in most cases).
Partial mocking is only useful when you want to test the functionality of an abstract class with mocked implementations of abstract methods. If you aren't doing this, you are likely not going to see much benefit from doing a partial mock.
If this is not an abstract class, you will want to focus more on the approach Modan suggests, which is to say that you should mock dependencies rather than your target class itself. All of this boils down to the rule don't mock what you are testing.

Categories

Resources