.netunit-testingpropertiesmockingssh.net

SSH.Net.Sftp Cannot mock non-overridable property


Using a unit test I need to bypass this code and reach return IsFile; line. The variable client is my own wrapper around SSH.Net SftpClient which I can mock. The enum SftpCheckPathExistence is my own custom enum.

code

SftpFileAttributes attrs = client.GetAttributes(fileName);
if (attrs.IsDirectory)
{
    return SftpCheckPathExistence.IsDirectory;
}

return SftpCheckPathExistence.IsFile;

unit test

clientMock.Setup(f => f.GetAttributes(It.IsAny<string>())).Returns(???);

The problem is I cannot mock the return of GetAttributes(filename) which is the class SftpFileAttributes.

1. Write no clientMock.Setup

SftpFileAttributes attrs = client.GetAttributes(fileName); // attrs is null
if (attrs.IsDirectory) // errors because its null

2. First try - return instantiated class

var sftpFileAttributes = new SftpFileAttributes(); // Class has no public constructor, this errors.
sftpFileAttributes.IsDirectory = false; // Property has private setter, this errors.

clientMock.Setup(f => f.GetAttributes(It.IsAny<string>())).Returns(sftpFileAttributes);

3. Second try - mock SftpFileAttributes

var sftpFileAttributesMock = new Mock<SftpFileAttributes>();
sftpFileAttributesMock.SetupGet(f => f.IsDirectory).Returns(false);
// This errors because Moq creates a derived class as a mock and IsDirectory is not marked virtual to be overriden.

clientMock.Setup(f => f.GetAttributes(It.IsAny<string>())).Returns(sftpFileAttributes.Object);

Error:

System.NotSupportedException
  HResult=0x80131515
  Message=Unsupported expression: f => f.IsDirectory
Non-overridable members (here: SftpFileAttributes.get_IsDirectory) may not be used in setup / verification expressions.
  Source=Moq
  StackTrace:
   at Moq.Guard.IsOverridable(MethodInfo method, Expression expression)

Solution

  • Managed to do it by creating my own classes having only the fields that I use. It is not perfect because it is error prone to reconstruct the whole functionalities from the SSH.NET classes. Fortunately, I needed only some simple properties.

    public class CustomSftpFileAttributes
    {
        public bool IsDirectory { get; set; }
    }
    

    method in Wrapper

    var sftpFileAttributes = sftpClient.GetAttributes(fileName);
    return new CustomSftpFileAttributes
    {
        IsDirectory = sftpFileAttributes.IsDirectory,
    };