Unit testing LINQ which returns an integer - c#

I have this test which verifies if I call the Query() in my reference.
[TestFixture]
public class When_retrieving_an_application_license
{
[Test]
public void available_licenses_should_be_counted()
{
// Arrange
var sut = new LicenseManager();
var mockILicenseRepository = new Mock<ILicenseRepository>();
sut.LicenseRepository = mockILicenseRepository.Object;
// Act
sut.GetLicenseCount(Guid.NewGuid(), Guid.NewGuid());
// Assert
mockIApplicationLicenseRepository.Verify(x => x.Query());
}
}
However, the GetLicenseCount(Guid.NewGuid(), Guid.NewGuid()) function looks like this:
public int GetLicenseCount(Guid cId, Guid appId)
=> LicenseRepository.Query()
.Count(al => al.CId == cId && al.AppId == appId
&& al.UserId == null
&& al.Expiry > DateTime.UtcNow);
Query() returns all in the repo to count which UserId's are in null.
Is it enough to say that the test is OK even if it only verifies the query() part of the linq?
How about the count?

If you are wanting to make sure the right count is being returned you will need to arrange your mocked ILicenseRepository to return the data you are expecting.
var mockILicenseRepository = new Mock<ILicenseRepository>();
mockILicenseRepository.Setup(x => x.Query()).Returns(new {CId = guid, AppId = guid2, Expiry = DateTime.Now.AddDays(1)};
You will also need to store the return value to assert against
var actualCount = sut.GetLicenseCount(Guid.NewGuid(), Guid.NewGuid());
Assert.AreEqual(expectedCount, actualCount);
However, if you are unit testing LINQ's Query method then I think you may want to restructure your production code because unit testing framework methods is unnecessary.

Related

Mocking a method return inside tested method

so I am trying to write an unit test for this method (I'm using xUnit and MOQ):
public override FilteredFeedPagesResult<ProgramPage> Create(FilteredFeedContext context)
{
var pages = _pageFilteringService.GetFilteredFeedPages(
context.Reference,
context.Culture,
context.Filters,
_customPageFilter);
if (context.IsSortedByDate && context.PageType.Name is nameof(ProgramPage))
{
var sortedPages = pages.OfType<ProgramPage>()
.Select(page => new
{
Page = page,
ScheduledStartDate = page.GetProgramPairings(page).Select(pairing => pairing.ScheduledStartDate).DefaultIfEmpty(DateTime.MaxValue).Min(),
})
.OrderBy(item => item.ScheduledStartDate)
.ThenBy(item => item.Page.Name)
.Select(item => item.Page);
return Map(sortedPages, context.PageNumber, context.PageSize);
}
return Map(pages.OrderByDescending(x => x.Date), context.PageNumber, context.PageSize);
}
As you can see, inside the LINQ statement in if clause there is a GetProgramPairings being invoked. It is supposed to get events for particular page from the database: Then, based on it, the order of events is created.
Code of the GetProgramPairings method:
public IEnumerable<ProgramPairing> GetProgramPairings(ProgramPage page)
{
var pairings = new List<ProgramPairing>();
if (page != null && page.ProgramPairings != null && page.ProgramPairings.FilteredItems.Any())
{
foreach (ContentAreaItem item in page.ProgramPairings.FilteredItems)
{
if (contentLoader.Service.TryGet<ProgramPairing>(item.ContentLink, out ProgramPairing pairing))
{
pairings.Add(pairing);
}
}
}
return pairings;
}
This is what my test looks like so far:
[Fact]
public void Create_IsSortedByDateTrueAndPageTypeProgramPage_ReturnsSortedPages()
{
var homePageMock = SetupHomePage();
var returnedPages = new[] { CreateProgramPage(DateTime.UtcNow.AddDays(-5)), CreateProgramPage(DateTime.UtcNow) };
var context = new FilteredFeedContext(homePageMock.Object, 0, 6, typeof(ProgramPage), null, null, true);
_filteredFeedPagesFilteringServiceMock.Setup(x => x.GetFilteredFeedPages<ProgramPage>(It.Is<ContentReference>(p => p.ID == homePageMock.Object.ContentLink.ID), It.Is<CultureInfo>(c => c.LCID == homePageMock.Object.Language.LCID), It.IsAny<IDictionary<string, string>>(), It.IsAny<IPageCustomFilter<ProgramPage>>()))
.Returns(returnedPages);
var result = _sut.Create(context);
//will need to create an assert to check if items in the list are in right order
}
My question is, how to mock the IEnumerable parings returned fromGetProgramPairings inside of the main method being tested ?
The problem here is the Single Responsibility Principle. Think thoroughly, is the ProgramPage's responsibility to get program pairings? This logic should be encapsulated in some other service. Once you do that, you can easily mock that service. Good luck!

Unit Testing a Retrieve TableOperation for Azure Table Storage

I have some code that I'd like to unit test.
I am retrieving some data from an Azure Storage Table database as part of my method that I'd like to test, so I need to mock out the return from the database.
Code to test:
public class GetCustomer : IGetCustomer
{
//constructor
public GetCustomer(IClientTableFactory clientTableFactory)
{
_partitionKey = "test";
_customersTable = clientTableFactory.GetStorageTable("customers");
}
//method to test
public async Task<string> GetCustomerNameAsync(string email)
{
//match on full email
var match = await SearchAsync(email.ToLower());
if (match == null)
{
//just match on email domain
var domain = email.ToLower().Substring(email.IndexOf("#"));
match = await SearchAsync(domain);
}
return match;
}
//internal method that queries Azure Table Storage
private async Task<string> SearchAsync(string searchString)
{
var query = TableOperation.Retrieve<Customer>(_partitionKey, rowkey: searchString);
var result = await _customersTable.ExecuteAsync(query);
var match = result.Result as Customer;
return match?.Name;
}
}
Unit Test so far:
//Arrange
var email = "Testy.McTest#Test.com.au";
var tableFactory = new Mock<IClientTableFactory>();
var customersTable = new Mock<CloudTable>(new Uri("http://unittests.localhost.com/FakeTable"));
customersTable.Setup(x => x.ExecuteAsync(It.IsAny<TableOperation>()))
.ReturnsAsync(new TableResult{ HttpStatusCode = 200, Result = new Customer{ Name = "jiminy crickets" }});
tableFactory.Setup(x => x.GetStorageTable("customers")).Returns(customersTable.Object);
var getCustomers = new GetCustomer(tableFactory.Object);
// Act
var result = await getCustomers.GetCustomerNameAsync(email);
// Assert
Assert.AreEqual("jiminy crickets", result);
Of course, the test passes every time. The missing piece of the puzzle that I would like to mock out is this line:
customersTable
.Setup(x => x.ExecuteAsync(It.IsAny<TableOperation>()))
.ReturnsAsync...
I should be able to replace It.IsAny<TableOperation>() with my search query eg It.Is<TableOperation>(y => y.RowKey == "testy.mctest#test.com.au" but unfortunately RowKey is inaccessible.
I've also tried
customersTable
.Setup(x => x.ExecuteAsync(TableOperation.Retrieve<Customer>(_partitionKey, rowkey: searchString))
but it never passes this code at runtime - maybe because of the ETag property?
Any ideas? I've seen plenty of answers about mocking Table Storage, but none about mocking Query results.
If you don't mind using reflection you can find the values in the internal members "RetrievePartitionKey" and "RetrieveRowKey".
I wrote a simple method:
private T GetInternalMember<T>(object obj, string propertyName)
{
Type objType = obj.GetType();
PropertyInfo propInfo = objType.GetProperty(propertyName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return (T)propInfo.GetValue(obj, null);
}
And I'm using it like:
cloudTable.Verify(x => x.ExecuteAsync(It.Is<TableOperation>(op => GetInternalMember<string>(op, "RetrievePartitionKey") == "TestPartitionKey"
&& GetInternalMember<string>(op, "RetrieveRowKey") == "TestRowKey")));
It's not really ideal, but it works for unit tests.

Assert duplicate element in unit testing

How can I to make a unit test check that a list of object not contains a duplicate element based on some properties.
Here is what I tried to do:
[Fact]
public void RecupererReferentielContactClient_CasNominal_ResultOk()
{
// Arange
var contactCoreService = Resolve<IContactCoreService>();
int clientId = 56605;
ICollection<Personne> listPersone = new List<Personne>();
// Act
WithUnitOfWork(() => listPersone = contactCoreService.RecupererReferentielDeContactClient(clientId));
// Assert
listPersone.ShouldSatisfyAllConditions(
() => listPersone.ShouldNotBeNull(),
() => listPersone.ShouldBeUnique());
}
How can I make my unit test using shouldly?
Group by all the properties you want to check, and then test if all the groups have exactly 1 item.
bool allUnique= listPersone
.GroupBy(p=> new {properties you want to check})
.All(g=>g.Count()==1);
Assert.True(allUnique)
actual.GroupBy(k => k.Id).ShouldAllBe(item => item.Count() == 1);
will show a non-unique item, if assert failed

Setup with ReturnsAsync, need to return passed in value but getting null

I need to mock my IVehicleRecordsRepository for some tests. So here's the repo interface:
public interface IVehicleRecordsRepository
{
Task<VehicleRecord> StoreAsync(VehicleRecord veh, Guid? userId = null);
//...
}
and now I try to mock it in the xUnit test so StoreMethod() should return the same value that was passed in as a parameter. Here's the test that tests this scenario:
[Fact]
public async Task ShouldGetValueFromMockedMethod()
{
var mockRepo = new Mock<IVehicleRecordsRepository>();
mockRepo
.Setup(repo => repo.StoreAsync(It.IsAny<VehicleRecord>(), Guid.NewGuid()))
.ReturnsAsync((VehicleRecord veh, Guid userId) => veh)
// tried this too -> .Returns((VehicleRecord veh, Guid userId) => Task.FromResult(veh))
;
VehicleRecord vr = new VehicleRecord(newVehicle, Guid.NewGuid());
var testVeh = await mockRepo.Object.StoreAsync(vr);
Assert.NotNull(testVeh); // ====> FAILS HERE
Assert.AreEqual(vr, testVeh);
}
So, how can I get the same value I passed into StoreAsync() in return ?
Moq version: 4.7.99.0
I've not used Moq, so forgive my ignorance.
In your act statement:
var testVeh = await mockRepo.Object.StoreAsync(vr);
you're only passing in the Vehicle Record ('vr'), but your mocked object is set up to also expect a Guid.NewGuid(), correct?
mockRepo.Setup(repo => repo.StoreAsync(It.IsAny<VehicleRecord>(), Guid.NewGuid()))
Could it be that it's not matching the expectation and therefore, never calls the "(mockObject.)ReturnsAsync" method?
Have you tried doing something like:
var guid = Guid.NewGuid;
VehicleRecord vr = new VehicleRecord(newVehicle, guid);
var testVeh = await mockRepo.Object.StoreAsync(vr, guid);
Or, perhaps simplifying it a bit, change your mockObject to not expect a Guid, since you're passing in only the VehicleRecord:
mockRepo.Setup(repo => repo.StoreAsync(It.IsAny<VehicleRecord>()))

How do I return a different value from a stub based on a lambda argument

I have the following sample test code
public Stage Test(Stage Stage)
{
var StartStage = StageRepository.Single(x => x.Order == 1);
var EndStage = StageRepository.Single(x => x.Order == 5);
var ErrorStage = StageRepository.Single(x => x.Name == "Error");
if (Stage == StartStage)
{
return EndStage;
}
else
{
return ErrorStage;
}
}
And I am trying to test it using the following unit test
[TestMethod]
public void XXXTest()
{
//// Arrange
var AutoMocker = new RhinoAutoMocker<StageService>(MockMode.AAA);
MockRepository mockRepository = new MockRepository();
var MockStageRepository = AutoMocker.Get<IRepository<Stage>>();
Stage StartStage = mockRepository.Stub<Stage>();
StartStage.Order = 1;
Stage EndStage = mockRepository.Stub<Stage>();
EndStage.Order = 5;
Stage ErrorStage = mockRepository.Stub<Stage>();
ErrorStage.Name = "Error";
System.Linq.Expressions.Expression<Func<Entities.Stage, bool>> StartParam = x => x.Order == 1;
MockStageRepository
.Stub(x => x.Single(Arg<System.Linq.Expressions.Expression<Func<Entities.Stage, bool>>>.Is.Equal(StartParam)))
.Return(StartStage);
System.Linq.Expressions.Expression<Func<Entities.Stage, bool>> EndParam = x => x.Order == 1;
MockStageRepository
.Stub(x => x.Single(Arg<System.Linq.Expressions.Expression<Func<Entities.Stage, bool>>>.Is.Equal(EndParam)))
.Return(EndStage);
System.Linq.Expressions.Expression<Func<Entities.Stage, bool>> ErrorParam = x => x.Order == 1;
MockStageRepository
.Stub(x => x.Single(Arg<System.Linq.Expressions.Expression<Func<Entities.Stage, bool>>>.Is.Equal(ErrorParam)))
.Return(ErrorStage);
StageService StageService = AutoMocker.ClassUnderTest;
//Act
var ReturnStage = StageService.Test(StartStage);
//Assert
Assert.AreEqual(ReturnStage, EndStage);
}
However this is not working as it is not returning anything when I call StageRepository.Single(). If I change the stub code to ignore the argument then it does return something but it will be the same object returned for each call to Single() which I don't want.
Is it possible to configure RhinoMocks in such a way as to return different objects from a stub depending on the lambda that is passed into it?
I think the root of your problem is that equality on the Expression<Func<T,U>> type is performed by reference rather than value. That means your telling Rhino Mocks to look for instances of expressions created in the test rather than the ones created in the code your testing.
Two possible approaches come to mind:
One would be to provide a way to pass the lambda expressions in to the Stage class from the test, so that when the argument checks happen they are working against the same instances.
Maybe something like:
internal void SetStartStage(Expression<Func<Entities.Stage,bool>> predicate)
{
...
}
The inverse of this would also work, i.e. provide the Expression objects as fields/properties that can be accessed by you're test, and then use those when setting up your mock:
internal Expression<Func<Entities.State,bool>> StartStagePredicate
{
get{ return x => x.Order == 1; }
}
Another option would be to use the Matches method on Args to see if the argument checks the Stage object state correctly. This would require creating some Stage objects in your test that would match the criteria:
var startStageTester = new Stage { Order = 1 };
MockStageRepository
.Stub(x => x.Single(Arg<System.Linq.Expressions.Expression<Func<Entities.Stage, bool>>>.Matches(y => y.Compile()(startStageTester)))
.Return(StartStage);
The call to Compile() is a little jarring, but since you're dealing with an Expression and not a straight-up lambda, you've got to compile it in order to evaluate it.
Now, if a Stage is something that is hard to create, then you may need to create a Mock/Stub of one (or use you're StartStage) and have it return 1 from the Order property (in the case of the StartStage anyway).
There are probably some others I'm not thinking of at the moment as well.
IF the linq condition is not important, I would propose to match it as any, something like this
repository.Stub(x => x.Find(Arg<System.Linq.Expressions.Expression<Func<Entity, bool>>>.Is.Anything)).Return(entitiesList.AsQueryable());
Hope this help.
Thanks for that. That worked a treat. The one thing that I was missing was the Compile method on an ExpressionTree. There is a small bug in your sample code (you use x twice). For completeness here is the working code.
MockStageRepository2
.Stub(x => x.Single(Arg<System.Linq.Expressions.Expression<Func<Entities.Stage, bool>>>.Matches(y => y.Compile()(StartStage2))))
.Return(StartStage2);

Categories