Newbie question about mocking and moq framework - c#

I've been using Moq framework in c# for mocking in unit tests however there is one thing I dont complete understand yet. I have this line of code
var feedParserMock = new Mock<ApplicationServices.IFeedParser>();
feedParserMock.Setup(y => y.ParseFeed(csv)).Returns(items).Verifiable();
The second line does it mean it will only return the value if the parameter passed is the same? because the parameter that I pass to ParseFeed inside my controller is build inside the controller and I dont have access to it in the unit test. Currently the method is returning null, is there any way to specify I want to return my items variable no matter what the parameter is?

Yes. Moq provides the It static class that has helper methods for specifying parameters that satisfy certain criteria. Your example could be:
feedParserMock.Setup(y => y.ParseFeed(It.IsAny<string>())).Returns(items).Verifiable();
Then Moq will match your setup, given that the parameter is of the specified type and non-null (I chose string here, you should of course replace that with the correct type of your parameter in order for the code to compile).
You can also pass a delegate that Moq will evalute in order to determine if the setup is a match. Example:
feedParserMock.Setup(y => y.ParseFeed(It.Is<string>(s => s.Length > 3));
This will match any method invocations on ParseFeed, where the parameter is a string with a Length larger than 3.
Check out the "Matching arguments" section of the Moq Quickstart guide to learn more.

Yes, you can Use It.IsAny()
for example
feedParserMock.Setup(y => y.ParseFeed(It.IsAny<string>())).Returns(items).Verifiable();

Related

Moq Setup does not work as expected in a separate class

I am using moq version 4.2 to unit test some controllers of web api 2 with EF as the ORM. Since a lot of tests need a mocked IEntityRepository<User> so I use a static method in a separate class called TestHelper to create such a fake repository so that I can just call this method in all the tests where needed. Here is the static method:
internal static IEntityRepository<User> GetSingleUserMockRepository(User user, bool noTracking = true, params Expression<Func<User, object>>[] properties)
{
var userRepository = new Mock<IEntityRepository<User>>();
if (properties.Any())
userRepository.Setup(x => x.GetSingleInclude(user.Key, noTracking, properties)).Returns(Task.FromResult(user));
else
userRepository.Setup(x => x.GetSingle(user.Key, noTracking)).Returns(Task.FromResult(user));
return userRepository.Object;
}
I am not showing other method details here because don't think they're relevant to my problem. The thing is when calling this static method in my tests and pass the returned user repository into controllers the test will fail because it cannot find the user i.e. Setup didn't work!. However, if I repeat the test implementation within my tests to create the mock repository as a local variable; everything works fine.
Namely, this doesn't work (where Devices is a navigation property on the User entity, again don't think the detail matters here) e.g. if I pass the returned userRepository into my controller the test will fail.:
var userRepository = TestHelper.GetSingleUserMockRepository(user, true, x=> x.Devices);
But this works e.g. if I just use a local variable in the test and pass the userRepository.Object into my controller everything works as expected:
var userRepository = new Mock<IEntityRepository<User>>();
userRepository.Setup(x => x.GetSingleInclude(user.Key, true, u => u.Devices)).Returns(Task.FromResult(user));
Can someone please explain why? I thought these two ways are equivalent but clearly not in practice.
This is maybe not a full answer (yet), but still to long to fit into a Stack Overflow comment.
When you do:
userRepository.Setup(x => x.GetSingleInclude(user.Key, noTracking, properties)).Returns(...);
you are saying: When GetSingleInclude is called with that user.Key and that noTracking and in particular that properties which is an array of expression trees, Moq shall return what you specify.
However, if Moq gets a call to GetSingleInclude where one or more of the arguments are not equal to the values you supplied, your setup is not relevant, and Moq returns instead the default value which is null.
(If you had used MockBehavior.Strict instead, it would have thrown an exception instead of silently just returning null, which could be more helpful for understanding the issue.)
So when are two arrays of expression trees equal? If Moq uses the default equality comparer for arrays, they are only "equal" when they are the same array instance. If Moq uses some entry-wise comparison, it will come down to whether each expression tree is equal as reference (i.e. same Expression<> instance). In any case you may have trouble.
The question is why it works in the other case. Does GetSingleInclude have special overloads for when the number of properties (expression trees) is little?
What is the result of running the code from this question?
I am saying that you may be facing the same problem as in the thread
Mocking and verifying call to method containing an Expression<Func<T,bool>> parameter.

Mocking the NHibernate JoinAlias with Moq

I have the following repository code that will return a Company object based on an ID value, searching across the standard Company table and an additional table named ExternalCompany.
public Company FindByIdJoin(long id)
{
ExternalCompany xcomp = null;
return Session.QueryOver<Company>()
.Where(p => p.ObjectId == id)
.JoinAlias(p => p.ExternalCompanies, () => xcomp, JoinType.LeftOuterJoin)
.SingleOrDefault<Company>();
}
The code returns values that I expect. However, the trouble I'm having is in writing a Moq unit test to handle the JoinAlias call.
In a simpler method, called FindById, the code is essentially the same except there is no line for JoinAlias. The unit test for this simpler method is:
[Test]
public void FindById_returns_Company_for_valid_Id()
{
// Arrange
Mock<IQueryOver<Company, Company>> mockQueryOver = new Mock<IQueryOver<Company, Company>>();
mockQueryOver.Setup(x => x.Where(It.IsAny<Expression<Func<Company, bool>>>())).Returns(mockQueryOver.Object);
mockQueryOver.Setup(x => x.SingleOrDefault()).Returns(fake_Company);
// Act
var result = _repository.FindById(fake_Company.ObjectId);
// Assert
Assert.IsNotNull(result);
mockQueryOver.VerifyAll();
}
This test works and passes without a problem (fake_Company and _repository are defined elsewhere).
The problem is trying to put a test together for the FindByIdJoin call. I have tried using an additional Setup line like this (which goes between the Where and SingleOrDefault Setup lines):
mockQueryOver.Setup(x => x.JoinAlias(It.IsAny<Expression<Func<Company>>>(), It.IsAny<Expression<Func<ExternalCompany>>>(), JoinType.LeftOuterJoin)).Returns(mockQueryOver.Object);
The system tells me that "the best overloaded method match for IQueryOver ... has some invalid arguments."
So, I tried a few other variations on the Setup, but could not find a workable pattern.
My question is: what Setup arguments will work for JoinAlias so that I can properly test the FindByIdJoin method? Thanks!
The particular overload of JoinAlias you are using is
IQueryOver<TRoot, TSubType> JoinAlias(
Expression<Func<TSubType, object>> path,
Expression<Func<object>> alias,
JoinType joinType);
So, your setup needs to match this. Based on how you setup your IQueryOver mock, the correct setup would then be
mockQueryOver.Setup(x => x.JoinAlias(
It.IsAny<Expression<Func<Company, object>>>(),
It.IsAny<Expression<Func<object>>>(),
JoinType.LeftOuterJoin))
.Returns(mockQueryOver.Object);
Shouldn't MOQ be used for behaviour tests? Such Data access tests seem to be state dependent and I think using mock objects for such a system under test is an overkill.

Passing a predicate function parameter in moq fails

I am trying to use moq to mock a function on my licence class.
The licence class has the following interface:
Licence TryGetLicence(Predicate<Licence> filter);
In my integration test I am using mef to lazy load objects. My class finds the mef loaded objects and needs to check if there are licences available. For my test I create two objects, one of which can be licenced. I want to use moq to only return a licence for this object and null for the other, just as the real class would. The problem I am having is that moq doesn’t like me passing in a predicate. I’m not sure if moq just doesn’t handle predicates in this way or am I just implementing this wrong?
Here are the lines of code I have in my test that sets up moq for the above interface:
var lic = new Licence
{
LicId = Guid.Parse("53024D4E-3A01-4489-A341-753D04748EB9"),
LicName = "test",
Count = 1,
ExpiryDate = DateTime.Now.AddDays(2)
};
var mockAgent = new Mock<ILicenceAgent>();
mockAgent.Setup(x => x.TryGetLicence (y => y.LicId == lic.LicId)) Returns(lic);
This builds but when the last line is hit it throws an Unsupported expression exception.
For other tests I have used:
mockAgent.Setup(x => x. TryGetLicence (It.IsAny<Predicate<Licence>>())).Returns(lic);
I can’t use this for my new test as it would return a valid licence for both objects I have loaded.
Can moq be used in the way I am trying to use it?
This should solve the problem:
Predicate<Licence> predicate = y => y.LicId == lic.LicId;
mockAgent.Setup(x => x.TryGetLicence (predicate)).Returns(lic);
When you create the predicate inside Setup call, lambda expression is evaluated as a part of the expression that will be passed as a parameter. We prevent that by making sure it's only a delegate on the line above.
If you have 2 licences - lic1 and lic2, you can setup mock like this:
mockAgent.Setup(x => x.TryGetLicence(It.Is<Predicate<Licence>>(/* add your specific condition for licence1 */ ))).Returns(lic1);
mockAgent.Setup(x => x.TryGetLicence(It.Is<Predicate<Licence>>(/* add your specific condition for licence2 */ ))).Returns(lic2);

Sequence contains no elements when mocking repository

I'm trying to mock the repository code below:
var simulatorInstance = bundleRepository
.FindBy<CoreSimulatorInstance>(x => x.CoreSimulatorInstanceID == instanceID)
.Single();
but I get an error that states the "Sequence contains no elements". I tried changing the .Single to SingleOrDefault, but that returns a null.
In my unit test I mocked my the repository using the following:
This does not work
this.mockedRepository.Setup(
x => x.FindBy<CoreSimulatorInstance>(
z => z.CoreSimulatorInstanceID == 2))
.Returns(coreSimulatorInstancesList.AsQueryable());
This work for now using the Is.Any because I only have one record
this.mockedRepository.Setup(
x => x.FindBy<CoreSimulatorInstance>(
It.IsAny<Expression<Func<CoreSimulatorInstance, bool>>>()))
.Returns(coreSimulatorInstancesList.AsQueryable());
I want to mock the code using the .Single.
My guess is that you're using Moq to setup the repository's FindBy method so that business logic code hits the mocked method when you're running your test.
I think that the issue is that Moq is unable to match the parameter you provided during the mock setup with the parameter you provide during the execution of your business logic code, resulting in your mocked repository method not being executed and coreSimulatorInstancesList not being returned.
Since the parameter you provided to Moq during setup is an expression
z => z.CoreSimulatorInstanceID == 2
even when your business logic code executes with instanceID of 2
x => x.CoreSimulatorInstanceID == instanceID
resulting in an expression that is equivalent to the one you setup in the mock, they are still not matched because they are different expressions. These are two different expression objects. I don't think there's a way for Moq to know that they are equivalent and match your mocked method based on that.
I would go with Is.Any approach. If you want to be more thorough I think you would need to hand build a custom fake repository class in this case.

Select parameter less constructor with MEF conventions

I am trying to use MEF conventions within the .NET Framework 4.5 and am stuck on something I thought should be simple.
I want to export a set of classes and all are working except for the one that has more than one constructor so MEF by default calls the constructor with the most parameters which is causing a break as the parameters are aren't importing which is how it should be I guess.
Anyway, I want to make sure it works by telling MEF to export the constructor with no parameters.
var registration = new RegistrationBuilder();
registration.ForTypesDerivedFrom<TestStepResult>()
.Export<TestStepResult>()
.SelectConstructor(xxx);
So I know I need to do something in the SelectConstructor but cannot find what should be there to say to call the constructor with no parameters.
One way to do this is:
registration.ForTypesDerivedFrom<TestStepResult>()
.Export<TestStepResult>()
.SelectConstructor(ctorInfos =>
{
var parameterLessCtor = ctorInfos.FirstOrDefault(ci => ci.GetParameters().Length == 0);
if (parameterLessCtor != null)
return parameterLessCtor;
else
return ctorInfos.First();
});
Note that it include some simple error handling. If there is no parameterless .ctor it returns the first one available. This might not be what you need though. You will have to decide on how to handle this case.
Can you not simply decorate the preferred constructor with the [ImportingConstructor] attribute?
AFAIK, the only step you're missing is:
registration.ForTypesDerivedFrom<TestStepResult>()
.Export<TestStepResult>()
.SelectConstructor(ctorInfos => ctorInfos[0]);
Where ctorInfos is contains the array of ctors you have for the export in question.

Categories