I was playing around with testing using machine specifications and there is something that i am just not able to do, was wondering if somebody have been there before,
Is there any way to using Rhino Mocks to create a stub for a method that uses a lambda expression, i found that i can do the following
Having this method in a sample class:
public void UpdateVisit(int userId){
var user = repository.FindBy<User>(x=>x.Id==userId && user.IsActive ==true);
user.Visit = user.Visit + 1;
repository.Save(user);
}
I can stub the method like this:
//...Inside test method
var user = new User();
repository.Stub(x=>x.FindBy<User>(Arg<Expression<Func<User,bool>>>.Is.Anything)).Return(user);
The thing is I would like to stub the method not to Any Lambda Expression, just for the specific lambda expression "x=>x.Id==userId && user.IsActive ==true", so that the test would fail if this expression changes in the method...
I guess i could create a mock repository that does not go to the database and test the behavior in the lambda though this, i was wondering if there is another approach to this...
Appreciate any suggestions on this,
Thanks
You don't want to test that the particular lambda expression is used in the method. You want to test the behavior that the method is suppose to have. Testing implementation details like a specific lambda expression is in general too brittle. Instead:
[Fact]
UpdateVisit_updates_Visit_for_user_that_is_in_the_repository_and_is_active() {
// set up mock repository with dummy user having
// userId == 1,
// IsActive == true,
// Visit = 42
// invoke UpdateVisit
// pull userId == 1 from the repository
Assert.Equal(43, user.Visit);
}
[Fact]
UpdateVisit_does_not_update_visit_for_user_that_is_not_active() {
// etc.
}
Related
I read a few tutorial on Moq C# package but I still can't really understand what is Setup and Returns in Moq.
Example,
mock.Setup(p => p.GetEmployeebyId(1)).ReturnsAsync("JK");
Example 2,
mock.Setup(x => x.Save(It.IsAny<DeskBooking>())).Callback<DeskBooking>(
deskBooking =>
{
savedDeskBooking = deskBooking;
});
)
TL;DR: Setup = When, Returns = What
Whenever you write unit tests then you want make sure that a given piece of functionality is working as expected. But most of the time the functionality depends on some other components / environment / external source / whatsoever.
To make your test focused and replayable we need to use test doubles. These will replace your dependencies during the test. We can categorize the test doubles like this:
Dummy: simple code that returns bogus data
Fake: a working alternative which can take shortcuts
Stub: custom logic with predefined data
Mock: custom logic with expectations (interactive stub)
Shim: custom logic at run-time (replace static with a delegate)
Spy: interceptors to record calls
So, whenever you want to create a mock then you have to tell that under what circumstances how should the component behave. In other words when the function is called with a particular input then what should be the expected output.
In case of Moq you can use the Setup to define the when. And the Returns to specify the what.
Here is a simple example. Let's suppose you have the following function:
private IService service;
string MyMethod()
{
int number = service.GetNextNumber();
if(number % 2 == 0)
{
return "even";
}
else
{
return "odd";
}
}
Then you can write the following to test cases:
public void GivenAnEvenNumber_WhenICallMyMethod_ThenItShouldReturnEven
{
//Arrange
var serviceMock = new Mock<IService>();
serviceMock
.Setup(svc => svc.GetNextNumber())
.Returns(2);
...
//Act
var result = SUT.MyMethod();
//Assert
Assert.Equal("even", result);
}
public void GivenAnOddNumber_WhenICallMyMethod_ThenItShouldReturnOdd
{
//Arrange
var serviceMock = new Mock<IService>();
serviceMock
.Setup(svc => svc.GetNextNumber())
.Returns(1);
...
//Act
var result = SUT.MyMethod();
//Assert
Assert.Equal("odd", result);
}
So, as you can see we have used Setup and Returns to direct the control flow in each test case.
Your second example can be considered a Spy, because there you are recording the input for latter assessment.
In example 1
mock.Setup(p => p.GetEmployeebyId(1)).ReturnsAsync("JK");
sets up your mock so when GetEmployeebyId is called with a 1 as the parameter, the mock will return "JK".
In example 2
mock.Setup(x => x.Save(It.IsAny<DeskBooking>())).Callback<DeskBooking>(
deskBooking =>
{
savedDeskBooking = deskBooking;
});
when the Save method is called with any parameter of type DeskBooking, the lambda function will save the parameter in the savedDeskBooking variable. You can then test that you've saved the DeskBooking you expected.
I have a unit test using MOQ that's behaving unexpectedly. I'm expecting the IsAuthorizedAsync method to always return true, but it's returning false. Here's a simplified version of the code that's adding the IsAuthorizedAsync method to my Mock Object.
public static IAuthenticationInterface GetAuthentication()
{
var mock = new Mock<IAuthenticationInterface>();
mock.Setup(e => e.IsAuthorizedAsync(It.IsIn<string>(), It.IsAny<MyEvent>())).Returns(System.Threading.Tasks.Task.FromResult(true)).Verifiable();
// return the mock object
return mock.Object;
}
Here's code similar to the code that's using it:
bool isAuthorized = this.mockObject != null && await this.mockObject.IsAuthorizedAsync("abc123", myEvent).ConfigureAwait(false);
Like I said, it's returning false when it looks to me like it should always return true. Is there any way for me to step into the lambda expression code? Alternatively, is there any way for me to view what the actual lambda expression that's being used when I call this.mockObject.IsAuthorizedAsync? I suspect it's not what I think it is.
-Eric
As per #tzachs' comment, note that the It.IsIn matcher takes a list of matching values (strings in your instance). It.IsIn() with an empty params or IEnumerable will never match anything, as it is implemented with .Contains:
public static TValue IsIn<TValue>(IEnumerable<TValue> items)
{
return Match.Create<TValue>((Predicate<TValue>)
(value => Enumerable.Contains<TValue>(items, value)),
(Expression<Func<TValue>>) (() => It.IsIn<TValue>(items)));
}
hence the failure to return the desired result. You'll want to either change this e.g.
It.IsAny<string>() // ... Any string at all
It.Is<string>(s => s == "Foo") // ... Match via a Predicate
It.IsIn<string>("Foo", "Bar", "Baz") // ... Match via a List
Also, note that when working with Async methods, that Moq (and Test Frameworks like NUnit and XUnit) have support for Async semantics. So instead of 'hacking' a Task.FromResult, what you can do instead is:
[Test]
public async void MyTest() // ... The UT can be made async
{
var mock = new Mock<IAuthenticationInterface>();
mock.Setup(e => e.IsAuthorizedAsync(It.IsIn<string>("Foo"), It.IsAny<MyEvent>()))
.ReturnsAsync(true) // ... Async
.Verifiable();
// async calls can be awaited
Assert.True(await mock.Object.IsAuthorizedAsync("Foo", null));
}
(and yes, I know I'm just testing the Mock here :)
I'm having an issue really testing the Querying side of my architecture where I'm calling into a repository that expects an Expression<Func<T, bool>> as parameter for filtering. I was trying to understand this article, where Mark is saying to use Stubs for queries instead.
Lets say I have a query handler:
public class GetUserByEmailQueryHandler : IQueryHandler<GetUserByEmailQuery, User>
{
private readonly IGenericRepository<User> userRepository;
public GetUserByEmailQueryHandler(IGenericRepository<User> userRepository)
{
this.userRepository = userRepository;
}
public User Handle(GetUserByEmailQuery query)
{
return this.userRepository.Find(u => u.Email == query.Email && u.IsLockedOut == false);
}
}
Now my test is going to look something like this:
[Fact]
public void Correctly_Returns_Result()
{
// arrange
var id = Guid.NewGuid();
var email = "test#test.com";
var userRepositoryMock = new Mock<IGenericRepository<User>>();
userRepositoryMock.Setup(
r =>
r.Find(It.IsAny<Expression<Func<User, bool>>>())).Returns(new User { UserId = id }).Verifiable();
// Act
var query = new GetUserByEmailQuery(email);
var queryHandler = new GetUserByEmailQueryHandler(userRepositoryMock.Object);
var item = queryHandler.Handle(query);
// Assert
userRepositoryMock.Verify();
Assert.Equal(id, item.UserId);
}
To me, this test is useless, especially using It.IsAny<Expression<Func<User, bool>>>() as I could be filtering by anything at all. The filter would be a crucial business logic that needs to be tested. How can I test an expression like this? Is this one of those reasons why a generic repository is bad and I should use a specific repository that take exactly the filter parameters that is needed? If that is the case, I'll be moving the expression from one layer to the other and I'd still need to test it
If I should use stubs as Mark said in his blog, are there any examples out there? Am I supposed to run this query on an in-memory list which will be used to validate that the filter expression is correct?
Is this one of those reasons why a generic repository is bad
Yes, it is. Additionally, if you want to follow the SOLID principles of OOD (not that you must, but they are often useful in order to understand the consequences of design decisions), "clients […] own the abstract interfaces" (Agile Principles, Patterns, and Practices, chapter 11). Thus, the interface used by the client should be defined in terms of what the client needs, not by what some general-purpose library exposes.
In this particular case, it looks like what the GetUserByEmailQueryHandler really needs is an ability to query based on an email address, so you could define a reader interface like this:
public interface IUserReader
{
User FindByEmail(string email);
}
This turns GetUserByEmailQueryHandler into something like this:
public class GetUserByEmailQueryHandler : IQueryHandler<GetUserByEmailQuery, User>
{
private readonly IUserReader userRepository;
public GetUserByEmailQueryHandler(IUserReader userRepository)
{
this.userRepository = userRepository;
}
public User Handle(GetUserByEmailQuery query)
{
return this.userRepository.FindByEmail(query.Email);
}
}
At this point, the GetUserByEmailQueryHandler class is so degenerate that you should seriously consider whether it adds any value.
The filter would be a crucial business logic that needs to be tested. How can I test an expression like this?
That really depends on where you want that business logic to execute in the final system. You could test a filter by running it in memory, but if you ultimately plan on executing it on a database server, you'll have to involve the database in your automated tests. That tends to suck, which is the case why most programmers are seriously looking for alternatives to relational databases.
Sorry, but if there's a solution to this particular problem, I don't know what it is.
Personally, I design my system so that they don't rely on complicated filter expressions, but only on simple filter expressions that I can treat as Humble Objects.
To me, this test is useless, especially using
It.IsAny<Expression<Func<User, bool>>>() as I could be filtering by
anything at all. The filter would be a crucial business logic that
needs to be tested. How can I test an expression like this?
No matter what abstraction is used it is needed to test filtering business logic. I answered the similar SO question "Why this mock with Expression is not matching?" a year ago and you can use a code example from it.
In order to test filtering business logic for your design I would change your code the following way:
[Fact]
public void Correctly_Returns_Result()
{
// Arrange
var validEmail = "test#test.com";
var userThatMatches = new User { UserId = Guid.NewGuid(), Email = validEmail, IsLockedOut = false };
var userThatDoesnotMatchByIsLockedOut = new User { UserId = Guid.NewGuid(), Email = validEmail, IsLockedOut = false };
var userThatDoesnotMatchByEmail = new User { UserId = Guid.NewGuid(), Email = "Wrong Email", IsLockedOut = true };
var aCollectionOfUsers = new List<User>
{
userThatMatches,
userThatDoesnotMatchByIsLockedOut,
userThatDoesnotMatchByEmail
};
var userRepositoryMock = new Mock<IGenericRepository<User>>();
userRepositoryMock
.Setup(it => it.Find(It.IsAny<Expression<Func<User, bool>>>()))
.Returns<Expression<Func<User, bool>>>(predicate =>
{
return aCollectionOfUsers.Find(user => predicate.Compile()(user));
});
var sut = new GetUserByEmailQueryHandler(
userRepositoryMock.Object);
// Act
var foundUser = sut.Handle(new GetUserByEmailQuery(validEmail));
// Assert
userRepositoryMock.Verify();
Assert.Equal(userThatMatches.UserId, foundUser.UserId);
}
You can use Return method which allows you to access passed expression and apply it to any target collection of users.
I've written a piece of code that is responsible for creating an Issue.It uses a visitor pattern to set the Issue assignee.
Here's the code :
public Issue CreateIssue(IssueType type, string subject, string description, Priority priority, string ownerId)
{
var issue = new Issue
{
...
};
IssueManagerContext.Current.IssueAssignmentMethodResolver(type).Visit(issue);
...
return issue;
}
I would like to test the functionality of this code thus somehow I need to mock the behavior of a visitor. After studying different Mock libraries I decided to use Moq.
But I don't know how should I build a mock object that gets an argument from my code instead of hard coding it as it's shown in the quick start guide.
Here's what I have done so far :
var visitor = new Mock<IIssueVisitor>();
visitor.Setup(x => x.Visit(null));
You can only match a specific instance of an object if the test has the same reference as the SUT. The problem in your scenario is that your SUT creates the instance issue, and returns it at the end of the method. Your test cannot access it while the method is executing, which precludes your mock object from being able to match it.
You can configure your mock object to match any Issue instance with the following syntax:
visitor.Setup(x => x.Visit(It.IsAny<Issue>()));
You can also configure the mock to conditionally match an Issue instance:
// Matches any instance of Issue that has an ID of 42
visitor.Setup(x => x.Visit(It.Is<Issue>(theIssue => theIssue.ID == 42)));
If you want to match the reference of a specific instance of Issue, then you'll have to move the instantiation logic into some kind of abstraction (e.g., a factory) of which your test could provide a fake implementation. For example:
// In SUT
var issue = issueFactory.CreateIssue();
...
// In test
var stubIssue = new Issue{ ... };
var issueFactory = new Mock<IIssueFactory>();
var visitor = new Mock<IIssueVisitor>();
...
issueFactory.Setup(factory => factory.CreateIssue())
.Returns(stubIssue);
visitor.Setup(x => x.Visit(stubIssue));
Use the following syntax:
interface IFoo
{
int Bar(string baz);
}
var mock = new Mock<IFoo>();
mock.Setup(x => x.Bar(It.IsAny<string>()))
.Returns((string baz) => 42 /* Here baz contains the value your code provided */);
This seems like a very simple task but I find it extremely hard to accomplish in Moq. I have a repository that calls a unit of work to query a random picture from a database. This query has one constraint; the random picture from the database cannot be equal to the current picture being displayed. I'm building an NUnit test for the repository and I'd like to mock the unit of work like so:
[TestFixture]
public class When_the_next_random_picture_for_TopSlidePicture_show_has_been_requested
{
private Guid _currentPictureID;
private Picture _randomPicture;
private Mock<IUnitOfWork<Guid>> _unitOfWorkMock;
[SetUp]
public void Context()
{
_currentPictureID = Guid.NewGuid();
_randomPicture = new Picture { ID = Guid.NewGuid() };
_unitOfWorkMock = new Mock<IUnitOfWork<Guid>>();
//TODO: Find out how to setup and verify expression when mocking method with equality comparison in a lambda expression.
_unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(pic => pic.ID != _currentPictureID))
.Returns(_randomPicture);
}
[Test]
public void The_PictureRepository_can_query_next_random_picture()
{
//Arrange
var picRepo = new PictureRepository(_unitOfWorkMock.Object);
//Act
var randomPicture = picRepo.GetNextRandomPicture(_currentPictureID);
//Assert
_unitOfWorkMock.Verify(uow =>
uow.GetRandom<Picture>(pic => pic.ID != _currentPictureID)
, Times.Once());
Assert.AreEqual(_randomPicture, randomPicture);
}
}
In the code above, the GetRandom<Picture>(Expression<Func<Picture, bool>>) in the UnitOfWork is supposed to return any picture in the database who's Guid ID isn't equal to the current pics ID. However, Setup() method called from _unitOfWorkMock returns null regardless of _randomPicture's value. After much research I found the following procedure:
_unitOfWorkMock = new Mock<IUnitOfWork<Guid>>();
_unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(It.IsAny<Expression<Func<Picture, bool>>>()))
.Returns(_randomPicture);
var randomPicture = picRepo.GetNextRandomPicture(_currentPictureID);
//Assert
_unitOfWorkMock.Verify(uow =>
uow.GetRandom<Picture>(It.IsAny<Expression<Func<Picture, bool>>>())
, Times.Once());
This allows the test to pass. BUT, I didn't test whether the picture returned from the db has the same Guid ID of the current picture ID passed in; which is the key principle for even building the test!!!
I love the Moq framework and prefer it over all other testing tools, but this seems like a massive breach of integrity as far as a unit testing platform goes. Please, someone, inform me on what I'm not seeing clearly and show me a simple and easy way to accomplish this seemingly simple task!
Gratitude
UPDATE
Thanks to #StriplingWarrior, I was able to solve the problem! His boolean algebra was wrong, but his answer was sound ;-) I found these modifications to my above code to work:
_unitOfWorkMock = new Mock<IUnitOfWork<Guid>>();
_unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e))))
.Returns(_randomPicture);
private bool TestIdMatchExpression(Expression<Func<Picture, bool>> expr)
{
var func = expr.Compile();
Assert.IsFalse(func(new Picture { ID = _referencePictureID }));
return true;
}
//Assert
_unitOfWorkMock.Verify(uow =>
uow.GetRandom<Picture>(It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e)))
, Times.Once());
Thanks again #StriplingWarrior!
You should be able to use a special overload of It.Is<>() to test the expression:
It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e))
From there you just have to figure out the best way to check the expression that gets passed in. The easiest way is probably to test the behavior: the expression should match a picture with the same guid, and reject a picture with a different one.
bool TestIdMatchExpression(Expression<Func<Picture, bool>> expr)
{
var func = expr.Compile();
Assert.IsTrue(func(new Picture{ID = _currentPictureID}));
Assert.IsFalse(func(new Picture{ID = Guid.NewGuid()}));
}
Remember, when you do unit testing of a method, you have to isolate that test, mock every external dependency including database in your case , do the test of that method for different conditions of the external dependencies
Picture randomPictureExpected = new Picture{ ID=Guid.NewGuid()};
_unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(pic=>pic.ID!=_currentPictureID))
.Returns(randomPictureExpected);
and your assert would be like
var randomPictureActual = picRepo.GetNextRandomPicture(_currentPictureID);
Assert.AreEqual (randomPictureExpected.ID, randomPictureActual.ID);