1

I'm attempting to provide a mock that will help me test:

ClaimsPrincipal princple = Thread.CurrentPrincipal as ClaimsPrincipal;

However from what I can tell, the "as" keyword returns null even though I can see in the debugger Thread.CurrentPrincipal is the mock.

To test the theory I put together this short demo:

void Main()
{
    var userMock = new Mock<IUser>();
    userMock.Setup(w => w.UserId).Returns(1);

    var user = userMock.Object as User;

    user.Dump(); // null

}

public interface IUser
{
    int UserId { get; set; }
}

public class User : IUser
{
    public int UserId { get; set; }
}

How can I provide moq's for code that use the as keyword in the background?

From what I understand perhaps I need to provide a way for the proxy to cast back?

I sort of realise that this isn't possible, but wondered what people's approaches are to solving this.

Charles
  • 50,943
  • 13
  • 104
  • 142
Alex KeySmith
  • 16,657
  • 11
  • 74
  • 152

2 Answers2

3

When you create mock

var userMock = new Mock<IUser>();

then Moq dynamically creates class which implements IUser interface. That class has no relation to other implementations of this interface (like User class). That's why mock object is IUser but it is not User:

var user = userMock.Object as User; // will be null
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • 1
    Thanks @Sergey, that's what I was thinking - thanks for reaffirming that. Do you have approaches you prefer when getting around situations like this? I'm guessing really I shouldn't need to moq this and should re-factor the whole area to suit. – Alex KeySmith Feb 25 '14 at 14:53
  • 1
    @AlexKey yep, you can see it by yourself in [`Mock`](https://code.google.com/p/moq/source/browse/trunk/Source/Mock.Generic.cs) source code. There is method `InitializeInstance` which creates proxy class – Sergey Berezovskiy Feb 25 '14 at 15:00
  • 1
    @AlexKey workaround is simple - make you code depend on interface which you are mocking instead of interface implementation – Sergey Berezovskiy Feb 25 '14 at 15:01
  • 1
    Thanks @Sergey, I just saw your comment whilst coming to the same conclusion. Thanks for your help +1 from me. – Alex KeySmith Feb 25 '14 at 15:03
2

I think I've found a work around, I understand I should be mocking against interfaces and shouldn't mock concrete classes, but this may have to do until I can refactor the dependencies.

The trick is to mock the concrete class Mock<User>() and use the As<IUser>() to mock the properties etc.

void Main()
{
    var userMock = new Mock<User>();
    userMock.As<IUser>().Setup(w => w.UserId).Returns(1);

    var user = userMock.Object as User;

    user.Dump(); // not null
}

public interface IUser
{
    int UserId { get; set; }
}

public class User : IUser
{
    public int UserId { get; set; }
}

I think I missed trying this as I've been always mocking to the interfaces in the past.

Alex KeySmith
  • 16,657
  • 11
  • 74
  • 152
  • 1
    I still consider that its better to depend on IUser in your code, but solution is interesing - `As` used to *add* interface implementations to generated proxy. I didn't think about mocking class and then adding interface mock to it – Sergey Berezovskiy Feb 25 '14 at 15:11
  • Yes I agree, depending on IUser is a much better idea in this context, but for "as ClaimsPrinciple" it is 'just about ok' before I do some more good'ol refactoring in the background. :-) – Alex KeySmith Feb 25 '14 at 15:47