Mocking a visitor object using Moq - c#

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

Related

What is Setup and Returns in MOQ C#?

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.

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.

Mock a method returning an interface with NInject Mocking Kernel

Say I have an interface like this.
public interface ICamProcRepository
{
List<IAitoeRedCell> GetAllAitoeRedCells();
IAitoeRedCell CreateAitoeRedCell();
}
How do I mock the method which return an interface and a list of interface objects. I am using Ninject.MockingKernel.Moq
var mockingKernel = new MoqMockingKernel();
var camProcRepositoryMock = mockingKernel.GetMock<ICamProcRepository>();
camProcRepositoryMock.Setup(e => e.GetAllAitoeRedCells()).Returns(?????WHAT HERE?????);
camProcRepositoryMock.Setup(e => e.CreateAitoeRedCell()).Returns(?????WHAT HERE?????);
In your case you need to create mocks of the desired results for the mocked interface in question and pass them into the Returns of its setups, either via kernel or straight moq. I don't know Ninject to be able to help you there but here is a plain Moq example
var mockingKernel = new MoqMockingKernel();
var camProcRepositoryMock = mockingKernel.GetMock<ICamProcRepository>();
var fakeList = new List<IAitoeRedCell>();
//You can either leave the list empty or populate it with mocks.
//for(int i = 0; i < 5; i++) {
// fakeList.Add(Mock.Of<IAitoeRedCell>());
//}
camProcRepositoryMock.Setup(e => e.GetAllAitoeRedCells()).Returns(fakeList);
camProcRepositoryMock.Setup(e => e.CreateAitoeRedCell()).Returns(() => Mock.Of<IAitoeRedCell>());
If the mocked objects need to provide fake functionality as well then the too will have to be setup accordingly.

AutoFixture creating a property with regex rule

I have recently applied this regex pattern attribute to one of the properties in my class in order to evaluate valid url formats. The problem has now occurred that AutoFixture cannot create an instance of it displaying the error
"AutoFixture was unable to create an instance from
Ploeh.AutoFixture.Kernel.RegularExpressionRequest, most likely because
it has no public constructor, is an abstract or non-public type."
I have tried a few suggestions like
var contact = _fixture.Build<ContactEntity>()
.With(c=>c.Customer.Website,
new SpecimenContext(_fixture)
.Resolve(new RegularExpressionRequest(Constants.UrlRegex)))
.Create();
and
public class WebsiteSpecimenBuilder: ISpecimenBuilder
{
public object Create(object request,
ISpecimenContext context)
{
var pi = request as PropertyInfo;
if (pi!=null && pi.PropertyType == typeof(string)
&& (pi.Name.Equals("Email") || pi.Name.Equals("Website")))
{
//tried both of these options
return (new OmitSpecimen() || "http://www.website.com";
}
return new NoSpecimen(request);
}
}
But i still can't get autofixture to create the class. Am i missing something to get it to create or is this regex too complex for autofixture to handle?
I seem to have gotten a solution by using the customize method as such:
_fixture = new Fixture();
_fixture.Customize<CustomerEntity>(ce =>
ce.With(x => x.Website, "http://suchTest.verwow"));
This returns any instance where the customer is called to have this website (or other regex properties). I don't really know if something in autofixture takes precedence as to why this one has worked in setting the website while the others haven't. But it is a solution that allows my testing to work
You should check the regex which is passed to RegularExpressionRequest()
new RegularExpressionRequest(Constants.UrlRegex)
The regex should be of generation type and not validation. For example, it can be as follows
string TopicSuffixValidation = #"[a-zA-Z0-9]{1,5}/[a-zA-Z0-9]{1,5}"
I use AutoFixture(4.17.0) and it implicitly referenced Fare(2.2.1)
You can do that:
var entity = new Fixture().Build<Entity>()
.With(x => x.variable, new Xeger(RegexPattern).Generate)
.Create();

SetupSequence in Moq

I want a mock that returns 0 the first time, then returns 1 anytime the method is called thereafter. The problem is that if the method is called 4 times, I have to write:
mock.SetupSequence(x => x.GetNumber())
.Returns(0)
.Returns(1)
.Returns(1)
.Returns(1);
Otherwise, the method returns null.
Is there any way to write that, after the initial call, the method returns 1?
The cleanest way is to create a Queue and pass .Dequeue method to Returns
.Returns(new Queue<int>(new[] { 0, 1, 1, 1 }).Dequeue);
That's not particulary fancy, but I think it would work:
var firstTime = true;
mock.Setup(x => x.GetNumber())
.Returns(()=>
{
if(!firstTime)
return 1;
firstTime = false;
return 0;
});
Bit late to the party, but if you want to still use Moq's API, you could call the Setup function in the action on the final Returns call:
var mock = new Mock<IFoo>();
mock.SetupSequence(m => m.GetNumber())
.Returns(4)
.Returns(() =>
{
// Subsequent Setup or SetupSequence calls "overwrite" their predecessors:
// you'll get 1 from here on out.
mock.Setup(m => m.GetNumber()).Returns(1);
return 1;
});
var o = mock.Object;
Assert.Equal(4, o.GetNumber());
Assert.Equal(1, o.GetNumber());
Assert.Equal(1, o.GetNumber());
// etc...
I wanted to demonstrate using StepSequence, but for the OP's specific case, you could simplify and have everything in a Setup method:
mock.Setup(m => m.GetNumber())
.Returns(() =>
{
mock.Setup(m => m.GetNumber()).Returns(1);
return 4;
});
Tested everything here with xunit#2.4.1 and Moq#4.14.1 - passes ✔
You can use a temporary variable to keep track of how many times the method was called.
Example:
public interface ITest
{ Int32 GetNumber(); }
static class Program
{
static void Main()
{
var a = new Mock<ITest>();
var f = 0;
a.Setup(x => x.GetNumber()).Returns(() => f++ == 0 ? 0 : 1);
Debug.Assert(a.Object.GetNumber() == 0);
for (var i = 0; i<100; i++)
Debug.Assert(a.Object.GetNumber() == 1);
}
}
Just setup an extension method like:
public static T Denqueue<T>(this Queue<T> queue)
{
var item = queue.Dequeue();
queue.Enqueue(item);
return item;
}
And then setup the return like:
var queue = new Queue<int>(new []{0, 1, 1, 1});
mock.Setup(m => m.GetNumber).Returns(queue.Denqueue);
Normally, I wouldn't bother submitting a new answer to such an old question, but in recent years ReturnsAsync has become very common, which makes potential answers more complicated.
As other have stated, you can essentially just create a queue of results and in your Returns call pass the queue.Dequeue delegate.
Eg.
var queue = new Queue<int>(new []{0,1,2,3});
mock.SetupSequence(m => m.Bar()).Returns(queue.Dequeue);
However, if you are setting up for an async method, we should normally call ReturnsAsync. queue.Dequeue when passed into ReturnsAsync and will result in the first call to the method being setup working correctly, but subsequent calls to throw a Null Reference Exception. You could as some of the other examples have done create your own extension method which returns a task, however this approach does not work with SetupSequence, and must use Returns instead of ReturnsAsync. Also, having to create an extension method to handle returning the results kind of defeats the purpose of using Moq in the first place. And in any case, any method which has a return type of Task where you have passed a delegate to Returns or ReturnsAsync will always fail on the second call when setting up via SetupSequence.
There are however two amusing alternatives to this approach that require only minimal additional code. The first option is to recognize that the Mock object's Setup and SetupAsync follow the Fluent Api design patterns. What this means, is that technically, Setup, SetupAsync, Returns and ReturnsAsync actually all return a "Builder" object. What I'm referring to as a Builder type object are fluent api style objects like QueryBuilder, StringBuilder, ModelBuilder and IServiceCollection/IServiceProvider. The practical upshot of this is that we can easily do this:
var queue = new List<int>(){0,1,2,3};
var setup = mock.SetupSequence(m => m.BarAsync());
foreach(var item in queue)
{
setup.ReturnsAsync(item);
}
This approach allows us to use both SetupSequence and ReturnsAsync, which in my opinion follows the more intuitive design pattern.
The second approach is to realize that Returns is capable of accepting a delegate which returns a Task, and that Setup will always return the same thing. This means that if we were to either create an an extension method for Queue like this:
public static class EMs
{
public static async Task<T> DequeueAsync<T>(this Queue<T> queue)
{
return queue.Dequeue();
}
}
Then we could simply write:
var queue = new Queue<int>(new []{0,1,2,3});
mock.Setup(m => m.BarAsync()).Returns(queue.DequeueAsync);
Or would could make use of the AsyncQueue class from Microsoft.VisualStudio.Threading, which would allow us to do this:
var queue = new AsyncQueue<int>(new []{0,1,2,3});
mock.Setup(m => m.BarAsync()).Returns(queue.DequeueAsync);
The main problem that causes all of this, as that when the end of a setup sequence has been reached, the method is treated as not being setup. To avoid this, you are expected to also call a standard Setup if results should be returned after the end of the sequence has been reached.
I have put together a fairly comprehensive fiddle regarding this functionality with examples of the errors you may encounter when doing things wrong, as well as examples of several different ways you can do things correctly.
https://dotnetfiddle.net/KbJlxb
Moq uses the builder pattern, setting up the behavior of the mocks.
You can, but don't have to use the fluent interface.
Keeping that in mind, I solved the problem this way:
var sequence = myMock
.SetupSequence(""the method I want to set up"");
foreach (var item in stuffToReturn)
{
sequence = sequence.Returns(item);
}

Categories

Resources