Reputation: 18783
I've inherited a small console application that makes calls to a SOAP web service. It's a tragic mess of nested try-catches that log exceptions in various ways, and I'd like to wrap some test coverage around how it behaves when a SoapException gets thrown.
Question: How can I mock a class like SoapException using Moq when I can't mock an interface and I can't make properties or methods "virtual"?
A little more explanation:
To test this error handling, I need to control the Actor
property of the SoapException object, as well as the Detail
property in order to verify the error handling.
A snippet of my unit test code:
[TestMethod]
public void MyTestMethod()
{
Mock<SoapException> soapMock = new Mock<SoapException>(MockBehavior.Strict);
soapMock.SetupGet<string>(ex => ex.Actor).Returns("Test Actor");
Since I'm mocking a concrete class, and the Actor
property is not marked "Virtual", Moq is throwing this exception when executing the SetupGet(...)
line during the test run:
System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: ex => ex.Actor
After some reading, the ideal answer is to mock an interface, which I am unable to do in this case. Since this is a class baked in to the .NET framework, I also can't magically mark the Actor
property as virtual.
How can I mock a SoapException, or is there a different way I can verify the error handling?
As an aside, I first dove into creating an actual SoapException with some XML nodes inside it, but I quickly fell down the rabbit hole of programmatically creating an XML document tree. I can do it, but it would require many more lines of test setup code, which I'd like to avoid if possible.
Upvotes: 4
Views: 1263
Reputation: 11
I was in a same situation to mock SoapException. I used the constructor of SoapException to pass Detail, Actor etc. Below is using Rhino Mocks.
//Build your xmlDocument
SoapException mockSoapException = MockRepository.GenerateMock<SoapException>("Mock SoapException", new XmlQualifiedName(), "TEST", xmlDocument);
Upvotes: 1
Reputation: 6775
Its not possible to mock it using Moq. One option is to use Shim from Microsoft Fakes Framework. You can use it in scenarios where the code you are trying to mock doesn't use interface or is a virtual method(like in your scenario).
See below explanation of Shim from msdn.
A shim modifies the compiled code of your application at run time so that instead of making a specified method call, it runs the shim code that your test provides. Shims can be used to replace calls to assemblies that you cannot modify, such .NET assemblies.
http://msdn.microsoft.com/en-us/library/hh549175.aspx
Note that Fakes framework is only available with Visual Studio Ultimate or Premium.
Upvotes: 1