Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking a method to throw an exception (moq), but otherwise act like the mocked object?

I have a Transfer class, simplified it looks like this:

public class Transfer {     public virtual IFileConnection source { get; set; }     public virtual IFileConnection destination { get; set; }      public virtual void GetFile(IFileConnection connection,          string remoteFilename, string localFilename)     {         connection.Get(remoteFilename, localFilename);     }      public virtual void PutFile(IFileConnection connection,          string localFilename, string remoteFilename)     {         connection.Get(remoteFilename, localFilename);     }      public virtual void TransferFiles(string sourceName, string destName)     {         source = internalConfig.GetFileConnection("source");         destination = internalConfig.GetFileConnection("destination");         var tempName = Path.GetTempFileName();         GetFile(source, sourceName, tempName);         PutFile(destination, tempName, destName);     } } 

The simplified version of the IFileConnection interface looks like this:

public interface IFileConnection {     void Get(string remoteFileName, string localFileName);     void Put(string localFileName, string remoteFileName); } 

The real class is supposed to handle a System.IO.IOException that is thrown when the IFileConnection concrete classes loses connectivity with the remote, sending out emails and what not.

I would like to use Moq to create a Transfer class, and use it as my concrete Transfer class in all properties and methods, except when the GetFile method is invoked - then I want it to throw a System.IO.IOException and make sure the Transfer class handles it properly.

Am I using the right tool for the job? Am I going about this the right way? And how would I write the setup for that unit test for NUnit?

like image 859
Jeremy Holovacs Avatar asked Apr 25 '12 21:04

Jeremy Holovacs


People also ask

What method allows for an exception to be outputted in MOQ?

To streamline the configuration of methods throwing exceptions, Moq has special constructs targeting this scenario: Throws and ThrowsAsync . Both methods accept an instance of any Exception type. . ThrowsAsync(new Exception("My custom exception"));

What is mock method?

Mock is a method/object that simulates the behavior of a real method/object in controlled ways. Mock objects are used in unit testing. Often a method under a test calls other external services or methods within it. These are called dependencies.

What happens when you mock an object?

What happens when you mock something? First of all, we should define what a mock is: In a unit test, mock objects can simulate the behavior of complex, real objects and are therefore useful when it is impractical or impossible to incorporate a real object into a unit test. Mocking makes sense in a unit testing context.

How can you check if a method was called using a mock?

Mockito verify() method can be used to test number of method invocations too. We can test exact number of times, at least once, at least, at most number of invocation times for a mocked method. We can use verifyNoMoreInteractions() after all the verify() method calls to make sure everything is verified.


1 Answers

Here's how you can mock your FileConnection

Mock<IFileConnection> fileConnection = new Mock<IFileConnection>(                                                            MockBehavior.Strict); fileConnection.Setup(item => item.Get(It.IsAny<string>,It.IsAny<string>))               .Throws(new IOException()); 

Then instantiate your Transfer class and use the mock in your method call

Transfer transfer = new Transfer(); transfer.GetFile(fileConnection.Object, someRemoteFilename, someLocalFileName); 

Update:

First of all you have to mock your dependencies only, not the class you are testing(Transfer class in this case). Stating those dependencies in your constructor make it easy to see what services your class needs to work. It also makes it possible to replace them with fakes when you are writing your unit tests. At the moment it's impossible to replace those properties with fakes.

Since you are setting those properties using another dependency, I would write it like this:

public class Transfer {     public Transfer(IInternalConfig internalConfig)     {         source = internalConfig.GetFileConnection("source");         destination = internalConfig.GetFileConnection("destination");     }      //you should consider making these private or protected fields     public virtual IFileConnection source { get; set; }     public virtual IFileConnection destination { get; set; }      public virtual void GetFile(IFileConnection connection,          string remoteFilename, string localFilename)     {         connection.Get(remoteFilename, localFilename);     }      public virtual void PutFile(IFileConnection connection,          string localFilename, string remoteFilename)     {         connection.Get(remoteFilename, localFilename);     }      public virtual void TransferFiles(string sourceName, string destName)     {         var tempName = Path.GetTempFileName();         GetFile(source, sourceName, tempName);         PutFile(destination, tempName, destName);     } } 

This way you can mock internalConfig and make it return IFileConnection mocks that does what you want.

like image 160
Ufuk Hacıoğulları Avatar answered Oct 10 '22 17:10

Ufuk Hacıoğulları