moq and the “as” keyword
-
21-12-2019 - |
Question
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.
Solution 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.
OTHER TIPS
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