Reputation: 1458
I have a class which is responsible for building PPT slides for exporting. To unit test this I have created an interface so it can be mocking using Moq; all great so far. However I run into difficulties when trying to test that my method has been called. It is a void method so at this point I only want to know that the method has been hit.
Here is my interface:
interface IPowerpointExporter
{
void AddSlides(int amount);
void setTitle(string title);
}
And here's my unit test:
[TestMethod]
public void testPPTObject()
{
var mockPPT = new Mock<IPowerpointExporter>();
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
mockPPT.Object.AddSlides(1);
mockPPT.VerifyAll();
}
However when I come to call AddSlides()
I get a GeneratorException
. The explanation for this is that my IPowerpointExporter was not accessible. I have a feeling this is because I am trying to call a method on an interface, though I'm unsure since I've got my object at mockPPT.Object.AddSlides();
at this point.
Note that I've also tried the following trying to use an actual object rather than Interface.Object. This also gives the same exception:
[TestMethod]
public void testPPTObject()
{
var mockPPT = new Mock<IPowerpointExporter>();
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);
mockPPT.VerifyAll();
}
Using Moq how can I check that my method has been called? Is what I'm doing above along the right lines?
Upvotes: 3
Views: 10204
Reputation: 15982
This exception occurs because IPowerpointExporter
interface is not accessible to Moq.
You can make your IPowerpointExporter
interface public
, and test runs perfectly:
public interface IPowerpointExporter
{
void AddSlides(int amount);
void setTitle(string title);
}
....
[TestMethod]
public void testPPTObject()
{
var mockPPT = new Mock<IPowerpointExporter>();
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);
mockPPT.VerifyAll();
}
However, when you need make tests to non-public types, you can use InternalsVisibleTo
attribute in your assembly to make types visible to Moq.
[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]
Upvotes: 1
Reputation: 23757
You're likely getting that exception because your interface is not public
, or otherwise visible to the Moq assembly. See this question to resolve that.
If this is just dummy code to help you learn Moq, then read no further.
However, if this an actual test that you think has value, then you have other more fundamental issues. In your first example, you're doing absolutely nothing to test your code! Let's go through it, line by line:
var mockPPT = new Mock<IPowerpointExporter>();
You created a mock of your IPowerpointExporter
interface, so far so good.
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
You told the mock to expect a call to it's AddSlide
method, with an argument of 1
, and that the method can be verified. No problem so far.
mockPPT.Object.AddSlides(1);
But here's where it goes off the rails. You're just invoking the method on your mock, the same one you just setup above. The Object
property is a dummy object, it can only do what it was setup to do and has no ties to your actual implementation!
mockPPT.VerifyAll();
Now you verified that you called all your verifiable methods. All you did in this test was verify that Moq works; your code was never touched.
Let's look at the changed code in your second example now:
ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);
That cast will never work. The Object
property is just some proxy (a dynamic type actually), generated by Moq that knows nothing about any concrete implementation of the interface it is mocking.
Upvotes: 5