Unit testing code using IQueryable - c#

I'm asked to write some unit tests for some functionality, but quite frankly I'm not so sure about the need or usefulness of doing so for this particular piece of code. I'm in no way trying to question the need or usefulness of unit testing in general.
The code in question is very trivial and gets used alot. Basically it's a wrapper around the .Skip() and .Take() extension methods. In my opinion the legitimacy of the methods as a whole is questionable.
The code is basically this:
public IQueryable<T> Page(IQueryable<T> query, int page, int size)
{
if(query == null) throw new ArgumentNullException("query");
if(page < 0) throw new ArgumentOutOfRangeException("page");
if(page < 0) throw new ArgumentOutOfRangeException("size");
return query.Skip(page * size).Take(size);
}
Of course I can unit test for the expected exceptions, but what else? Could very well be that I'm missing the point, so what's up with this?

You can just hand in a static collection by calling AsQueryable
List<T> dummyData = new List<T>();
//Add data
var result = Page(dummyData.AsQueryable(), 0, 10);
//Perform assertions on result.
If you are in-fact just trying to test that your pagination works correctly.

You can test quite a few things here:
Check for proper guards (the exceptions that are thrown when invalid parameters are passed).
Check that Skip was called with the correct parameter.
Check that Take was called with the correct parameter.
Check that Skip was called before Take.
Points 2 - 4 are best tested with a mock. A mocking framework comes in handy here.
This kind of testing is called "interaction-based testing".
You could also use "state-based testing" by calling the method under test with a list with data and check that the returned data is the correct subset.
A test for point 2 could look like this:
public void PageSkipsThePagesBeforeTheRequestedPage()
{
var sut = new YourClass();
var queryable = Substitute.For<IQueryable<int>>();
sut.Page(queryable, 10, 50);
queryable.Received().Skip(500);
}
This test uses NSubstitute as mocking framework.

I'm sure, there is a strong need to test this method.
First of all, because of the bug:
if(page < 0) throw new ArgumentOutOfRangeException("page");
if(page < 0) throw new ArgumentOutOfRangeException("size");
You're not checking the size variable in fact.
Anyway, there is no need to perform the "integrated" testing - you can simply mock your IQueryable object and perform the unit testing. (see this answer: How do I mock IQueryable<T>)
In my opinion, it is an absolutely right thing to do to test this method.

In fact, since IQueryable<T> may encapsulate an underlying data storage - which is the case of Entity Framework's queryables -, we're talking about integration tests.
In my case, if I'd need to test something like your piece of code, I'd store some test data in the database for later query for it.
Since I can expect the results, I can perform an assertion in order to check if the tested method returned the expected result.
UPDATE
Since I see some confusion with the downvote and some comments, I'd like to point out that I've answered this taking in account the fact that the answer is tagged as for Entity Framework and I guess that the queryable was obtained from the DbSet.

Related

What is Moq's equivalent of LastCall in RhinoMocks?

I'm upgrading to .Net Core which involves converting a number of unit tests from RhinoMocks to Moq since it supports .Net Standard.
I've been converting LastCall by repeating the most recent mocked call, but I'm confused because I have a unit test where LastCall.Throw(Exception); occurs before any mocked calls do.
As I understand LastCall, it allows you to do something additional to the last call that was added, but I know I don't understand something because in my mind LastCall can't come before at least one mocked call.
The unit test looks something like:
MockRepository mock = new MockRepository();
...
using (mocks.Record())
{
nonMockedObject.DoSomething();
LastCall.Throw(Exception);
Expect.Call(mockedObject.Stuff()).Return(true).Repeat.Any();
...
}
Any help on understanding RhinoMocks's LastCall or how to convert it to Moq would be appreciated.
From the link, https://www.codeproject.com/Articles/11294/Rhino-Mocks-2-2#Capabilities,
Below are some important points to be noted.
We use the Expect.Call() for methods that has return values, and
LastCall for methods that return void to get the IMethodOptions
interface. I find the Expect.Call() syntax a bit clearer, but there is
no practical difference between the two.
I would recommend using Expect wherever possible (anything that return
a value). For properties setters, or methods returning void, the
Expect syntax is not applicable, since there is no return value.
Thus, the need for the LastCall. The idea of Last Call is pervasive in
the record state, you can only set the method options for the last
call - even Expect.Call() syntax is merely a wrapper around LastCall.
Conclusion : Do not use LastCall inside record state. As you are migrating from RhinoMocks to Moq, You can Ignore LastCall.
Coming to the code which you have shared, You can mock functions which returns a value using moq as below,
Mock<IYourRepository> mockRepository = new Mock<IYourRepository>();
mockRepository.Setup(m=> m.YourMethodName(It.IsAny<int>())).Returns(new List<string>());
mockRepository.Setup(m=> m.YourMethodName(It.Is<int>(x=> x == 0)).Throws<ArgumentException>();
For Methods which do not return anything, You can set like below,
Mock<IYourRepository> mockRepository = new Mock<IYourRepository>();
mockRepository.Setup(m=> m.YourVoidMethodName(It.IsAny<int>())).Verifiable();;
mockRepository.Setup(m=> m.YourVoidMethodName(It.IsAny<int>())).Throws<Exception>();
mockRepository.Setup(m=> m.YourAsyncVoidMethodName(It.IsAny<int>())).Returns(Task.Completed); // public async Task YourAsyncVoidMethodName(){}
To address the comment,
LastCall.Repeat.AtLeastOnce(); would be converted to Moq as
Mock<IYourRepository> mockRepository = new Mock<IYourRepository>();
mockRepository.Verify(m=> m.NotVoidMethodName(It.IsAny<int>()), Times.AtLeastOnce());

Using FakeItEasy with Linq Expression Parameter

I am trying to use learn how to use FakeItEasy, and wanted to try using it with some data access code from an old project I have access to. While the basics of FIE seemed pretty easy, and I was able to get simple cases working, this one has me stumped.
The system used Entity Framework, and one of the data management classes handles Users, and I'm trying to figure out how to test just the basic GetUserByUserNumber function. I can use a fake IPersistenceManager<User> when instantiating the UserDataManager class, and then call the GetUserByUserNumber method, but the assertion to check that userPersistenceManager.ReadCustom was called always fails.
I've tried calling the Delete method on the fake userPersistenceManager, and the assertion for that works fine. I think it has something to do with the Linq Expression that the ReadCustom method takes as its first parameter. I just don't know how that should be handled. Any help with this would be appreciated!
This is the method in the UserDataManager that I'm trying to test:
public User GetUserByUserNumber(string userNumber, bool loadRelatedRecords = false)
{
if (string.IsNullOrWhiteSpace(userNumber))
{
throw MyAppExceptions.CreateMyAppFatalException(Constants.ExceptionKeys.Unexpected, new ArgumentNullException("userNumber"));
}
Logger.Write(string.Format("Executing GetUserByUserNumber with UserNumber {0}.", userNumber), LogCategory.General, TraceEventType.Verbose);
return _UserPersistenceManager.ReadCustom(mem => mem.UserNumber == userNumber, EntityConstants.EntityNames.UserDetail);
}
This is the IPersistenceManager method that I want to ensure is called:
TEntity ReadCustom(Expression<Func<TEntity, bool>> predicate, string includeEntityName);
This is my unit test:
[TestMethod]
public void GetUserByUserNumber_Calls_ReadCustom()
{
// Arrange
var userPersistenceManager = A.Fake<IPersistenceManager<User>>();
var dataManager = new UserDataManager(userPersistenceManager);
// Act
dataManager.GetUserByUserNumber("123456", false);
// Assert
A.CallTo(() => userPersistenceManager.ReadCustom(u => u.UserNumber == "123456", EntityConstants.EntityNames.UserDetail)).MustHaveHappened();
}
I think Tim Long's answer is essentially correct although my slant is not that this is a failing of mocking frameworks—it comes down to how easy it is (in general, not just when mocking) to determine whether two things are "the same".
The problem you have is that unless told otherwise, FakeItEasy uses .Equals to compare the arguments. Expressions don't compare well with .Equals, and so you'll get a mismatch.
One option is to explore Expression equality-checkers. There are a number of questions on StackOverflow about this already, such as How to check if two Expression<Func<T, bool>> are the same. If you can find a good way to determine the equality of the expressions, I think you could provide that method to FakeItEasy's argument matcher
(e.g. with A<Expression<Func<TEntity, bool>>.That.Matches(…)).
Alternatively, you can go Mr. Long's route and capture the argument and then interrogate it later. I suggested a similar approach just a bit ago when answering
How to fake an action<> with FakeItEasy.
In your case, you could capture the predicate and then verify its correctness by seeing how it reacts to various input objects - does it like ones with UserNumber "123456".
This seems to be an area of mocking frameworks that is very counter-intuitive and hard to use correctly. I generally shy away from doing argument matching and try to return or capture some sort of object that I can later make assertions against.
In your case, you are essentially comparing two expressions for equality. The 'look' different in the code even though they have the same syntax. I wonder, can you create those two expressions outside of the test context and see if they compare equal then?

What to test/mock?

Given the following simple service class, in the GetCategories() method, should you test the fact that the categoryRepository.Query() method was called, or should you be setting up a test that keeps a list of categories and returns those?
I guess what I am saying is would mocking the categoryRepository and verifying that it's Query method was called once cover this test case?
public class CategoryService : ValidatingServiceBase, ICategoryService
{
private readonly IRepository<Category> categoryRepository;
private readonly IRepository<SubCategory> subCategoryRepository;
private readonly IValidationService validationService;
public CategoryService(
IRepository<Category> categoryRepository,
IRepository<SubCategory> subCategoryRepository,
IValidationService validationService)
: base(validationService)
{
this.categoryRepository = categoryRepository;
this.subCategoryRepository = subCategoryRepository;
this.validationService = validationService;
}
public IEnumerable<Category> GetCategories()
{
return categoryRepository.Query().ToList();
}
}
Sample Test
[Fact]
public void GetCategories_Should_CallRepositoryQuery()
{
var categoryRepo = new Mock<IRepository<Category>>();
var service = new CategoryService(categoryRepo.Object, null, null);
service.GetCategories();
categoryRepo.Verify(x => x.Query(), Times.Once());
}
It doesn't matter. In both cases (mock + behavior verification vs stub + assertion) you achieve exactly the same result and require exactly the same level of details about inner workings of class. Stick to whichever one you think is more suited in given scenario.
Unit test you posted is an example of behavior verification. You don't assert any values but instead check whether some method was called. This is especially useful when method call has no visible results (think about logging) or doesn't return any value (obviously). It of course has drawbacks, especially when you do such verification for methods that do return value, and don't check it (as is your case - we'll get to it).
The stubbing and asserting approach uses the collaborators to generate value. It doesn't check whether methods were called (at least not directly, yet such test is performed when you setup stub and that setup works), but instead relies on correct flow of stubbed value.
Let's go with simple example. Say you test a method of your class, PizzaFactory.GetPizza which looks like this:
public Pizza GetPizza()
{
var dough = doughFactory.GetDough();
var cheese = ingredientsFactory.GetCheese();
var pizza = oven.Bake(dough, cheese);
return pizza;
}
With behavior verification you'd check whether doughFactory.GetDough was called, then ingredientsFactory.GetCheese and finally oven.Bake. Had such calls indeed been made, you'd assume pizza was created. You don't check that your factory returns pizza, but assume it happens if all process' steps were completed. You can already see that drawback I mentioned earlier - I can call all the correct methods but return something else, say:
var dough = doughFactory.GetDough();
var cheese = ingredientsFactory.GetCheese();
var pizza = oven.Bake(dough, cheese);
return garbageBin.FindPizza();
Not the pizza you ordered? Notice that all the correct calls to collaborators happened just as we assumed they would.
With stub + assert approach it all looks similar except instead of verification you have stubbing. You use values generated by earlier collaborators to stub later collaborators (if somehow you get wrong dough or cheese, oven will not return pizza we wanted). The final value is what your method returns and this is what we assert:
doughFactoryStub.Setup(df => dg.GetDough).Return("thick");
ingredientsFactoryStub.Setup(if => if.GetCheese()).Return("double");
var expectedPizza = new Pizza { Name = "Margherita" };
ovenStub.Setup(o => o.Bake("thick", "double")).Return(expectedPizza);
var actualPizza = pizzaFactory.GetPizza();
Assert.That(actualPizza, Is.EqualTo(expectedPizza));
If any part of the process fails (say doughFactory returns normal dough) then the final value will be different and test will fail.
And once again, in my opinion in your example it doesn't matter which approach you use. In any normal environment both methods will verify the same thing and require same level of knowledge about your implementation. To be extra safe you might want to prefer to use the stub + assert approach in case somebody plants you a garbage bin1. But if such thing happens, unit tests are your last problem.
1 Note however that it might not be intentional (especially when complex methods are considered).
Yes, that would be the way.
mockCategoryRepository.Setup(r => r.Query()).Returns(categories)
var actualCategories = new CategoryService(mockCategoryRepository, mock..).GetCategories();
CollectionAssert.AreEquivalent(categories, actualCategories.ToList());
It would look something similar with Moq and NUnit.
What you've presented is a white-box test - an approach also possible in unit testing, but recommended only for simple methods.
In the answer presented by Sruti the service is tested in a black-box sense. The knowledge about the inner method is used only to prepare the test, but you don't verify if the method was called one time, 10 times, or wasn't called at all. Personally, I verify method calls only to verify that some external API that must be stubbed is used correctly (example: sending e-mails). Usually it is sufficient not to care about how a method works, as long as it's producing correct results.
With black-box tests the code and the tests are easier to maintain. With white-box tests, most changes of some internal structure during refactoring of a class usually must be followed by changing test code. In black-box approach you have more freedom to rearrange everything, and still be sure that interface's external behaviour hasn't changed.

How would you test it? How many tests?

I have this class (it's more pseudocode)
public class Roles
{
private ProcessData processData;
Roles(ProcessData pd)
{
processData = pd;
}
public string[] GetLoginsThatCanCallAction(string actionName)
{
return GetPeopleThatCanCallActionFromDb(actionName)
.Union(processData.ProcessOwner)
.Union(GetFromDb(Role.Administrators);
// there may be many more Union(xyz) calls here
.ToArray();
}
// I can refactor those methods to be mockable
private GetPeopleThatCanCallActionFromDb(...)
private GetFromDb(...)
}
Now my question is. Would you write one test for each Union call in GetLoginsThaatCanRunAction method?
Or is is just enough that I write one test and assert that method returns logins returned from all methods called inside GetLoginsThatCanCallAction.
I can see reasons to do it both ways. But maybe someone will convince me to on or the other solution.
Edit:
I think I wasn't clear with my question: I wanted to ask if you would write this test
var pd = new ProcessData()
pd.ProcessOwner = "Owner";
var r = new Roles(processData)
SetupSoThatCallsForPeopleThatCanCallActionWillReturn("Joe");
SetupSoThatCallForAdministratorsWillReturn("Administrator");
var logins = r.GetLoginsThatCanCallAction("some action");
Assert.That(logins, Contains("Owner");
Assert.That(logins, Contains("Joe");
Assert.That(logins, Contains("Administrator");
or would you split it into 3 separate tests with one Assert in each one?
Interesting topic, Your problem is that you are trying to write a test case after you have some code developed. I would have 1 test for each Union call. The reason being do you want to test that you get a value returned from all methods OR do you want to test that under different assumptions EACH method will return a login ?
For me its more important knowing that each method will return a login based on different use cases than a generic test that will return me pass / fail.
I hope that makes sense.
I would write one test for GetLoginsThatCanCallAction mocking the external objects. From your example, that would possibly mean mocking the Union calls. The reason being, when I am writing this code, I am not concerned with the logic being used in Union. (I have had cases where I haven't even written them yet).
If the union calls behavior can change, (IE it throws an exception), I would have a test for each of those. However, I would have my test-suite generating those test cases for me rather than trying to write them all by hand.
You are concerned that the GetLoginsThatCanCallAction behaves correctly. You also want to have control over what the Union calls return as well.
That being said, you would also want to have an automated test that executes the entire process that GetLoginsThatCanCallAction gets used in so that you are verifying the connections between the classes that you are mocking in the unit test. Barring that not being possible actually executing the process yourself manually.
One other note, if the class is hard to test. That is a code smell that your design is not as modular as it could be.
I would also avoid mocking internal methods of a class, if you need to do that to test the function. It is a sign that your class has another class hiding inside. Your class is doing more than one thing the S in SOLID
You should exercise only public API of unit under test. Your unit has single public method GetLoginsThatCanCallAction. It does not matter whether this method call other methods, or implemented as one large method. That's an implementation details. What really matters is whether this method correctly communicates with dependency and returns expected result:
// Arrange
Mock<IProcessData> processData = new Mock<IProcessData>();
processData.Setup(d => d.ProcessOwner).Returns(new[] { "Bob" });
var expected = new []{ "Bob", "Joe" };
// Act
var actual = roles.GetLoginsThatCanCallAction("Drink");
// Assert
processData.VerifyGet(d => d.ProcessOwner); // verify communication
CollectionAssert.AreEquivalent(expected, actual); // verify result

How to verify that method was NOT called in Moq?

How do I verify that method was NOT called in Moq?
Does it have something like AssertWasNotCalled?
UPDATE: Starting from Version 3.0, a new syntax can be used:
mock.Verify(foo => foo.Execute("ping"), Times.Never());
Run a verify after the test with the Times.Never() option.
_mock.Object.DoSomething()
_mock.Verify(service => service.ShouldntBeCalled(), Times.Never());
UPDATE: Since version 3, check the update to the question above or Dann's answer below.
Either, make your mock strict so it will fail if you call a method for which you don't have an expect
new Mock<IMoq>(MockBehavior.Strict)
Or, if you want your mock to be loose, use the .Throws( Exception )
var m = new Mock<IMoq>(MockBehavior.Loose);
m.Expect(a => a.moo()).Throws(new Exception("Shouldn't be called."));
Stolen from: John Foster's answer to the question, "Need help to understand Moq better"
One of the things that you might want to test is that the pay method
does not get called when a person aged over 65 is passed into the
method
[Test]
public void Someone_over_65_does_not_pay_a_pension_contribution() {
var mockPensionService = new Mock<IPensionService>();
var person = new Person("test", 66);
var calc = new PensionCalculator(mockPensionService.Object);
calc.PayPensionContribution(person);
mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never);
}
This does not work in recent versions of Moq (since at least 3.1), it should be specified in the Verify method as mentioned in the
answer.
Actually, it's better to specify .AtMost(0) after the Returns statement.
var m = new Mock<ISomething>();
m.Expect(x => x.Forbidden()).Returns("foo").AtMost(0);
Although the "throws" also works, AtMost(0) is more expressive IMHO.
Using VerifyNoOtherCalls (requires Moq 4.8 or later)
This answer is an indirect approach. Instead of checking that a particular method wasn't called, you check that no unexpected calls were made in general.
Consider that a thorough test of a mock does 2 things:
Verify that all expected calls were made
Verify that no unexpected calls were made
If you're already doing step 1, adding step 2 is trivial:
// Step 1 (if relevant - see note below)
mock.Verify(..., Times.Exactly(2));
mock.Verify(..., Times.Once());
// ...
// Step 2
mock.VerifyNoOtherCalls();
Notes
If you omit step 1, step 2 will simply ensure no calls were made to the mock at all.
This does not require a strict mock.
Source: Moq Quickstart
I realise this is a very old question, but it just appeared in my sidebar, and I'd like to add my solution.
Many unit tests appear to mock several functions, as part of the setup, but then aren't used during the test.
Surely it's better to enable strict mocking (which means anything not explicitly setup will throw an exception), and then don't set up any functions you don't expect to be called. Or to put it another way, only set up the functions that one test expects to be called, and anything else will thrown an exception.
var thingBeingTested = new Mock<IThink>(MockBehaviour.Strict);
thingBeingTested.ThisWillThrowAnExceptionBecauseItHasNotBeenMocked();
Suppose you have this method and you want to test that it's not being called
//Setup
var databaseSessionMock = new Mock<IDatabaseSession>();
databaseSessionMock.Setup(m => m.Commit()).Returns(true).Verifiable();
RepositoryFactory.Configure<IDatabaseSession>(databaseSessionMock.Object);
you can test like this
databaseSessionMock.Verify(m => m.Commit(It.IsAny()), Times.Never(), "Database Session mock object was not used");
Use .AtMostOnce();
After the real test, call the method again. If it throws an exception, it was called.

Categories

Resources