Mocking indexed property - c#

I am writing unit tests using Moq. I have created a mock object. Now when i try to mock its property i am getting error "An expression tree may not contain an indexed property"
here is my code.
public Node GetNode(IMyInterface interface, string itemName)
{
return interface.Items[itemName];
}
Here is the unit test
var expected = new Node();
var itemName = "TestName";
var mock = new Mock<IMyInterface>();
mock.Setup(f => f.Items[itemName]).Returns(expected);
var target = new MyClass();
var actual = target.GetNode(mock.Object, itemName);
Assert.AreEqual(expected, actual);
This line is giving me error.
mock.Setup(f => f.Items[itemName]).Returns(expected);
How can i moq this function.

Interface was a COM object and there were get function, so instead of directly accessing property using indexer use get function,
mock.Setup(f => f.get_Items(itemName)).Returns(expected);

Using Moq in ASP.NET Core 2.2, the get_Items setup does not work. But this does:
Mock<IConfiguration> configuration = new Mock<IConfiguration>();
configuration.Setup(x => x[key]).Returns(value);

Related

Why C# Xunit Mock returning empty enumeration on IQueryable

trying to mock one method in repository which having return IQueryable.
Please see the unit test method
[Fact]
public void TestMethod()
{
var mockZonal = new Mock<IBaseRepository<ZonalDefinition>>().SetupAllProperties();
var list = new List<ZonalDefinition>() { new ZonalDefinition() { DestinationZone = "401" } }.AsQueryable();
mockZonal.Setup(r => r.GetQueryableFromSql<ZonalDefinition>(new SqlQuerySpec(), new FeedOptions())).Returns(()=>list);
_repoFactory.Setup(r => r.GetGenericRepository<ZonalDefinition>(It.IsAny<string>(), It.IsAny<string>())).Returns(mockZonal.Object);
var afShipmentDetail = new AirFreightShipmentDetail();
var response = _quoteRespository.SetCXShipmentTargetValue(afShipmentDetail);
Assert.NotNull(response);
}
while executing the test am getting the result for mocked method 'GetQueryableFromSql' as 'Enumeration yielded no results'
enter image description here
As far as I understand Moq, you have to setup your method differently:
mockZonal.Setup(r => r.GetQueryableFromSql<ZonalDefinition>(It.IsAny<SqlQuerySpec>(),
It.IsAny<FeedOptions>()))
.Returns(()=>list);
The way you set it up, it would only match if those exact objects were passed to the method (which they won't).
If you need to be more specific with regards to the parameters to match, have a look at the documentation.

How to provide mock values in a FeedResponse for CosmosSDK v3+?

I'm writing a data access layer for my application and trying to mock out the CosmosDB SDK dependency for unit testing. I am using NUnit with NSubstitute and have come across the issue where I am trying to mock the return values for Container.GetItemQueryIterator.
I have successfully provided a mock feedIterator as a response for that call and a mock feedResponse as a return value for feedIterator.ReadNextAsync, but I cannot figure out how to inject any sort of values into the FeedResponse to test against
The code I'm trying to test looks like this:
var feedIterator = container.GetItemQueryIterator<T>(queryDefinition);
while (feedIterator.HasMoreResults){
result.success = true;
foreach (var item in await feedIterator.ReadNextAsync()){
list.Add(item);
}
}
My attempt at mocking out the dependencies like this (Simplified):
this.mockFeedResponse = Substitute.For<FeedResponse<T>>(this.mockApplicationList);
this.mockFeedIterator = Substitute.For<FeedIterator<T>>();
this.mockFeedIterator.ReadNextAsync().ReturnsForAnyArgs(Task.FromResult(this.mockFeedResponse));
this.mockFeedIterator.HasMoreResults.Returns(true);
Looking at the AzureCosmosDB SDK documentation, there seems to be a FeedResponse constructor for mocking that takes an IEnumerable as a parameter, but NSubstitute complains telling me it can't find this constructor when I attempt to pass in a list to use. Is there an alternative that I can feed some IEnumerable as a FeedResponse? Where am I going wrong?
I also managed the issue by mocking the GetEnumerator call on the FeedResponse mock. However, something to keep in mind is that if you just set mockFeedIterator.HasMoreResults(true), you'll end up in an infinite loop.
I solved that problem by using Moq's Callback method feature. I configured the HasMoreResults method to return true, and then setup a callback on the ReadNextAsync method to reconfigure HasMoreResults to return false. That way, it will drop into the while loop the first time, populate the return collection based on the mocked GetEnumerator method, and then exit the loop and return that collection to the test method.
var myItems = new List<MyItem>
{
new MyItem(),
new MyItem()
};
var feedResponseMock = new Mock<FeedResponse<MyItem>>();
feedResponseMock.Setup(x => x.GetEnumerator()).Returns(myItems.GetEnumerator());
var feedIteratorMock = new Mock<FeedIterator<MyItem>>();
feedIteratorMock.Setup(f => f.HasMoreResults).Returns(true);
feedIteratorMock
.Setup(f => f.ReadNextAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(feedResponseMock.Object)
.Callback(() => feedIteratorMock
.Setup(f => f.HasMoreResults)
.Returns(false));
var containerMock = new Mock<Container>();
containerMock
.Setup(c => c.GetItemQueryIterator<MyItem>(
It.IsAny<QueryDefinition>(),
It.IsAny<string>(),
It.IsAny<QueryRequestOptions>()))
.Returns(feedIteratorMock.Object);
You can mock ReadNextAsync to return a mock of FeedResponse that only has GetEnumerator() defined. The GetEnumerator of the List you create will then be passed through to the underlying implementation of the foreach.
The following example uses Moq, but you should be able to do something similar in your implementation.
var mockFeedResponse = new Mock<FeedResponse<Thing>>();
mockFeedResponse
.Setup(x => x.GetEnumerator())
.Returns(
new List<Thing>
{
new Thing(),
new Thing()
}.GetEnumerator()
);
For what it's worth - I worked around this by changing my code to access the Resource field on the FeedResponse received from CosmosDB. In my tests, I was able to then mock the return value for Resource and get the desired result.

Modifying mock property which has been set up

I'm going to simplify a bit the problem:
In my tests, I use a mocked object (I mocked it because it calls a bdd) which I give in parameters to a method of another object (not mocked) whose purpose is to modify a property of this mocked object.
ModifyingClass myModifyingClass = new ModifyingClass();
Mock<ToModifyClass> mockedClass = new Mock<ToModifyClass>();
mockedClass.Setup(mc => mc.name).Returns("Test1");
myModifyingClass.modify(mockedClass.Object);
The method modify then try to set the property name of the mocked object, but it won't work, so maybe it's the normal behavior but I really need to test if all of this work and if the method modify set the property as I want.
As mentioned in the comments you need to setup the mocked class differently in order to retain the values passed to properties.
Reference Moq - Quickstart
Stub all properties on a mock (not available on Silverlight):
mock.SetupAllProperties();
The example test provided would then look like...
//Arrange
var myModifyingClass = new ModifyingClass();
var mockedClass = new Mock<ToModifyClass>();
mockedClass.SetupAllProperties(); //<-- this will allow property changes to be retained.
var model = mockedClass.Object;
//set the property now that it can be set
model.name = "Test1";
var expected = "expected value here";
//Act
myModifyingClass.modify(model);
//Assert
var actual = model.name;
Assert.AreEqual(expected, actual);
//... other assertions
In Moq one would need to setup the getter.
mockedClass.SetupGet(mc => mc.name).Returns("Test1");

Moq and Find Expressions - Null Reference Exception

I'm fiddling with Moq and I can't figure out why the following proof-of-concept snippet is throwing a NullReferenceException when accessing mock.Object.SingleOrDefault:
var myObject = new MyObject() { Id = 1, Name = "Name" };
var mock = new Mock<MyInterface<MyObject>>();
mock
.Setup(t => t.Find(It.IsAny<Expression<Func<MyObject, bool>>>()))
.Returns(myObject);
var mySecondObject = mock.Object.SingleOrDefault(a => true);
Assert.AreEqual(myObject, mySecondObject);
Any clues?
I'm assuming your MyInterface inherits IQueryable.
Then, when you call SingleOrDefault on that, it calls IQueryable.Provider property on the instance provided.
Since you have not mocked IQueryable.Provider property, it returs null from a mock, so you've got a NullReferenceException.
Try to set MockBehavior.Strict to see if that's the cause.

Mocking a visitor object using Moq

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 */);

Categories

Resources