How to get Moq to verify method that has an out parameter - c#

I have an interface definition where the method has an out parameter defined
public interface IRestCommunicationService
{
TResult PerformPost<TResult, TData>(string url, TData dataToSend, out StandardErrorResult errors);
}
I have the following class that is using the above interface
public TripCreateDispatchService(IRestCommunicationAuthService restCommunicationService, ISettings settings)
{
_restCommunicationService = restCommunicationService;
_settings = settings;
}
public FlightAlert CreateTrip(string consumerNumber, PostAlertModel tripModel, out StandardErrorResult apiErrors)
{
url = .. code ommited
var result = _restCommunicationService.PerformPost<FlightAlert, PostAlertModel>(url), tripModel, out apiErrors);
return result;
}
In my unit tests I am trying to verify that the PerformPost Method of the RestCommunication object is called.
But no matter what I do, I cannot get Moq to verify that the method was called
public void DispatchService_PerformPost()
{
var consumerNumber = ...
var trip = ...
var result = ...
var apiErrors = new StandardErrorResult();
... code to setup mock data
_mockRestCommunicationService = new Mock<IRestCommunicationAuthService>();
_mockEestCommunicationService.Setup(x => x.PerformPost<string, PostAlertModel>(It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors)).Verifiable();
_systemUnderTest.CreateTrip(consumerNumber, trip, out apiErrors);
_mockRestCommunicationService.Verify(m =>
m.PerformPost<StandardErrorResult, PostAlertModel>(
It.IsAny<string>(),
It.IsAny<PostAlertModel>(), out apiErrors
), Times.Once);
}
But I am receiving the following error
Moq.MockException :
Expected invocation on the mock once, but was 0 times:
m => m.PerformPost<StandardErrorResult,PostAlertModel>(It.IsAny<String>(), It.IsAny<PostAlertModel>(), .apiErrors)
No setups configured.
How do I go about verifying that the method was called.
I am using Moq and NUnit
UPDATE 1
As per the comment from Sunny, I have modified the test to use a callback as follows
var consumerNumber = ...
var trip = ...
var result = ...
StandardErrorResult apiErrors;
_mockRestCommunicationService.Setup(x => x.PerformPost<string, PostAlertModel>(
It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors))
.Callback<string, PostAlertModel, StandardErrorResult>
((s, m, e) => e.Errors = new System.Collections.Generic.List<StandardError>()
{
new StandardError { ErrorCode = "Code", ErrorMessage = "Message" }
});
_systemUnderTest.CreateTrip(consumerNumber, trip, out apiErrors);
Assert.That(apiErrors.Errors, Is.Not.Null);
This is the error that is now being thrown when executing the test.
System.ArgumentException : Invalid callback. Setup on method with
parameters (String,PostAlertModel,StandardErrorResult&)
cannot invoke callback with parameters (String,PostAlertModel,StandardErrorResult).
at Moq.MethodCall.ThrowParameterMismatch(ParameterInfo[] expected, ParameterInfo[] actual)
at Moq.MethodCall.SetCallbackWithArguments(Delegate callback)
at Moq.MethodCallReturn`2.Callback(Action`3 callback)
This error is thrown at the Setup statement.
FYI. I am using Resharper 8 and using their test runner to execute my tests.
If I try to add the out parameter to the callback, the code will not compile.
I get the same error if I modify the setup to
_mockRestCommunicationService.Setup(x => x.PerformPost<string, PostAlertModel>(
It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors))
.Callback
((string s, PostAlertModel m, StandardErrorResult e) => e.Errors = new System.Collections.Generic.List<StandardError>()
{
new StandardError { ErrorCode = "Code", ErrorMessage = "Message" }
});

In the project I am working on we have used out It.Ref<T>.IsAny where T is the out parameter type (Moq version 4.14). This is because out is used as a parameter modifier, such that the value are passed by reference instead of by value.
In your case the verify method could look like this:
_mockRestCommunicationService.Verify(
_ => _.PerformPost<StandardErrorResult, PostAlertModel>(
It.IsAny<string>(),
It.IsAny<PostAlertModel>(),
out It.Ref<StandardErrorResult>.IsAny
),
Times.Once
);
To make sure no other unexpected invocations happened, you can also add:
_mockRestCommunicationService.VerifyNoOtherCalls()

It's better to actually use AAA and not verify the mock. Setup your method to return some specific result and assert that the result have been returned:
var myCommResult = new PostAlertModel();
_mockEestCommunicationService
.Setup(x => x.PerformPost<string, PostAlertModel>(It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors)
.Returns(myCommResult);
var response = _systemUnderTest.CreateTrip(consumerNumber, trip, out apiErrors);
Assert.AreSame(myCommResult, response);
The above will validate that the method was called, based on the example code.
If for some reason, the code in the question is not really representative of the real code, and there is no way to assert on the return of the method, than you can use Callback instead, and put something in the errors so you can verify.
Something like:
_mockEestCommunicationService
.Setup(x => x.PerformPost<string, PostAlertModel>(It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors))
.Callback( (string s, PostAlertModel m, StandardErrorResult e) => e.Add("Some error to test");
And later verify that apiErrors has the error you inserted in the callback.

Related

Moq not matching method

I have a method
Task<Document> GetCampaignById(Tenant tenant, string language, string campaignId);
that I am trying to mock:
mockLocator.Setup(l => l.GetCampaignById(
It.IsAny<Tenant>(),
It.IsAny<string>(),
It.IsAny<string>()))
.Returns(Task.FromResult(dummy));
I did, at first have "not set up" output but I am not getting any at all now and the test just shows as failed. I have tried changing to ReturnsAsync(dummy) but that did not alter my output at all. moq is set to strict but I don't think that should matter.
As far as I can tell I am setting this up with the correct parameter types and the correct return type but the test seems to fail before it even starts. Can anyone shed any light on this?
Full Test
[TestCase(1)]
[TestCase(2)]
[TestCase(3)]
[TestCase(4)]
[TestCase(5)]
public async Task ShouldCallUpdaterForEveryTenantResolved(int tupleCount)
{
// Arrange
var tenantTuples = CreateTenantTuples(tupleCount);
var mockTenantResolver = MockRepository.Create<ITenantResolver>();
mockTenantResolver.Setup(tr => tr.GetTenantTuples(It.IsAny<string>()))
.Returns(tenantTuples);
var mockCampaignIngestionService = MockRepository.Create<ICampaignIngestionService>();
var dummy = new Document();
var mockLocator = MockRepository.Create<IVehicleSearchStockUpdater>();
mockLocator.Setup(l => l.GetCampaignById(
It.IsAny<Tenant>(),
It.IsAny<string>(),
It.IsAny<string>()))
.Returns(Task.FromResult(dummy));
mockLocator.Setup(l => l.UpsertNewStockLevel(
It.IsAny<Document>(),
It.IsAny<OmegaConnector.Functions.PartnerCommunicator.Models.ChangeStockInfo>()))
.Returns(Task.FromResult(dummy));
var sut = new CampaignIngestionProcessor(
mockTenantResolver.Object,
mockCampaignIngestionService.Object,
mockLocator.Object);
var data = GetSimpleTestData();
data.NewStock = 5;
// Act
await sut.SubmitChangeStock(data);
// Assert
mockLocator.Verify(l => l.GetCampaignById(
It.IsAny<Tenant>(),
It.IsAny<string>(),
It.IsAny<string>()),
Times.Exactly(tupleCount)
);
mockLocator.Verify(l => l.UpsertNewStockLevel(
It.IsAny<Document>(),
It.IsAny<OmegaConnector.Functions.PartnerCommunicator.Models.ChangeStockInfo>()),
Times.Exactly(tupleCount)
);
}

Rhino Mock Test Expected #1, Actual #0 - error

I'm newbie working with Rhino Mock and I'm getting this error that I cannot understand why. Here the test
public void TestGet()
{
var installationReference = new Guid("21D7D135-6E9E-4F92-8313-873CA3ABDCD8");
var study = MockRepository.GenerateMock<IStudy>();
var installation = MockRepository.GenerateMock<IInstallation>();
var license = MockRepository.GenerateMock<ILicense>();
var participant = MockRepository.GenerateMock<IStudyParticipant>();
var clinicalPartner = MockRepository.GenerateMock<IClinicalPartner>();
clinicalPartner.Stub(c => c.FirstName).Return("John");
clinicalPartner.Stub(c => c.LastName).Return("Doe");
installation.Stub(i => i.Reference).Return(installationReference);
license.Stub(l => l.Installations).Return(new List<IInstallation> { installation });
participant.Stub(p => p.Licenses).Return(new List<ILicense> { license });
participant.Stub(p => p.ClinicalPartner).Return(clinicalPartner);
participant.Stub(p => p.ClinicalPartnerStatus).Return(ClinicalPartnerStatus.Active);
study.Stub(s => s.Description).Return("Test WebAPI");
study.Stub(s => s.Participants).Return(new List<IStudyParticipant> { participant });
repository.Stub(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference))))
.Return(new DummyResult<IStudy>(study));
repository.Expect(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference)))).Return(new DummyResult<IStudy>(study)).Repeat.Once();
repository.VerifyAllExpectations();
}
My GetStudiesByInstallationReference.cs
public class GetStudiesByInstallationReference : IQuery<IStudy>
{
public Guid InstallationReference { get; set; }
public GetStudiesByInstallationReference(Guid installationReference)
{
InstallationReference = installationReference;
}
public IQueryResult<IStudy> Execute(ISession session)
{
var criteria = session.CreateCriteria<IStudy>();
criteria.CreateAlias("participants", "p");
criteria.CreateAlias("p.licenses", "l");
criteria.CreateAlias("l.installations", "i");
criteria.Add(Restrictions.Eq("i.Reference", InstallationReference));
criteria.Add(Restrictions.Eq("Status", StudyStatus.Approved));
criteria.Add(Restrictions.Eq("p.ClinicalPartnerStatus", ClinicalPartnerStatus.Active));
criteria.Add(Restrictions.Le("StartDate", DateTime.Now));
criteria.Add(Restrictions.Or(
Restrictions.IsNull("EndDate"),
Restrictions.Gt("EndDate", DateTime.Now)));
return new CriteriaResult<IStudy>(criteria);
}
}
I want to test GetStudiesByInstallationReference was called one time.
What am I doing wrong?...it should pass the test as the Expect clause is the same used in the Stub but I still got the exception
Expected #1, Actual #0.
Anybody could help me with this?
Thanks in advance
I want to test GetStudiesByInstallationReference was called one time.
GetStudiesByInstallationReference is a type, and not a method that you expect to be called.
repository
.Expect(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference))))
.Return(new DummyResult<IStudy>(study)).Repeat.Once();
This line from your code is setting up an expectation on the repository mock. It expects that the Query() method is called with a parameter of type GetStudiesByInstallationReference that has the correct installation reference GUID as a property. If this method isn't called with the correct parameter, you will get the error you describe when calling repository.VerifyAllExpectations().
It looks like your test is missing the actual call to the SUT i.e. the "Act" in Arrange/Act/Assert. Simply put, you need to execute some code that will cause the method on your repository to be called as you expect (or change the test).

Moq: Test parameters sent with sequence of method calls

I'm new to C# Moq (used Rhino Mochs in the past) and needing to test a sequence of calls to the same method. I found this cool solution that tests a sequence of return values:
http://haacked.com/archive/2009/09/29/moq-sequences.aspx/
public static class MoqExtensions
{
public static void ReturnsInOrder<T, TResult>(this ISetup<T, TResult> setup,
params TResult[] results) where T : class {
setup.Returns(new Queue<TResult>(results).Dequeue);
}
}
What I need to do is to test the values sent as a parameter to the method (rather than the values it returns) in a sequence of calls to the same method.
Rough outline ...
var expression = new MyExpressionThing();
processor.Setup(x => x.Execute(expected1)).Verifiable();
processor.Setup(x => x.Execute(expected2)).Verifiable();
processor.Setup(x => x.Execute(expected3)).Verifiable();
expression.ExecuteWith(processor.Object);
processor.Verify();
Here's what I've attempted but I'm getting the exception:
"System.ArgumentException : Invalid callback. Setup on method with parameters (String,Object[]) cannot invoke callback with parameters (String)."
// Arrange
var processor = new Mock<IMigrationProcessor>();
IList<string> calls = new List<string>();
processor.Setup(p => p.Execute(It.IsAny<string>()))
.Callback<string>(s => calls.Add(s));
// Act
var expr = new ExecuteScriptsInDirectoryExpression { SqlScriptDirectory = #"SQL2\1_Pre" };
expr.ExecuteWith(processor.Object);
// Assert
calls.ToArray().ShouldBe(new[]
{ "DELETE FROM PRE1A", "DELETE FROM PRE1B", "INSERT INTO PRE2\r\nLINE2" });
Looks like I'm using boilerplate code from the Moq "Getting Started" examples:
This link discusses this exception and links to the Moq code that fires it.
http://dailydevscoveries.blogspot.com.au/2011/04/invalid-callback-setup-on-method-with.html
I would use a callback to capture the parameter each time the mock is called, and then assert the result:
var parameters = new List<ParameterType>();
processor.Setup(x => x.Execute(It.IsAny<ParameterType>()))
.Callback<ParameterType>(param => parameters.Add(param));
CallCodeUnderTest(processor.Object);
Assert.That(parameters, Is.EqualTo(new[] { expected1, expected2, expected3 }));
Update: Based on the error message you quoted, it looks like the method you're mocking takes a second parameter that's a params object[]. You don't need to specify that parameter when you call the method (which is why you don't need it in the Setup lambda), but you do need to specify it in the generic type parameters to .Callback. Change your Callback line to:
.Callback<string, object[]>((s, o) => calls.Add(s));

how to assert if a method has been called using nunit

is it possible to assert whether a method has been called? I'm testing the following method and I want to assert that the _tokenManager.GetToken() has been called. I just want to know if the method has been called as the method does not return a value. I am using Moq.
Thanks,
Code snippet
public void Subscribe(string code, string emailAddress, string columnKey)
{
// Request authentication token
var token = _tokenManager.GetToken(code, false);
if (!_tokenValidator.Validate(token))
{
// Token has expired or invalid - refresh the token
token = _tokenManager.GetToken(code, true);
}
// Subscribe email
_silverpopRepository.Subscribe(token.AccessToken, emailAddress, columnKey);
}
You should mock TokenManager and TokenValidator, and then create two unit test cases:
Case 1: token is validated and GetToken is called exactly once
Case 2: token is not validated and GetToken is called exactly twice
Case 1:
[Test]
public void Subscribe_TokenIsValidated_GetTokenIsCalledOnce()
{
// Arrange:
var tokenManagerMock = Mock.Of<TokenManager>();
var tokenValidatorMock = Mock.Of<TokenValidator>(x =>
x.Validate(It.IsAny<Token>()) == true);
var subscriber = new Subscriber
{
TokenManager = tokenManagerMock,
TokenValidator = tokenValidatorMock
};
// Act:
subscriber.Subscribe(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<string>());
// Assert:
Mock.Get(tokenManagerMock).Verify(x =>
x.GetToken(It.IsAny<string>(), It.IsAny<bool>()), Times.Once);
}
Case 2:
[Test]
public void Subscribe_TokenIsExpiredOrInvalid_GetTokenIsCalledTwice()
{
// Arrange:
var tokenManagerMock = Mock.Of<TokenManager>();
var tokenValidatorMock = Mock.Of<TokenValidator>(x =>
x.Validate(It.IsAny<Token>()) == false);
var subscriber = new Subscriber
{
TokenManager = tokenManagerMock,
TokenValidator = tokenValidatorMock
};
// Act:
subscriber.Subscribe(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<string>());
// Assert:
Mock.Get(tokenManagerMock).Verify(x =>
x.GetToken(It.IsAny<string>(), It.IsAny<bool>()), Times.Exactly(2));
}
Alternatively, you can create an unit test without mocking TokenValidator and verify if GetToken() has been called at least once. However, creating two cases as in the first example is preferred as we are testing all code paths.
// Arrange:
var tokenManagerMock = Mock.Of<TokenManager>();
var subscriber = new Subscriber {TokenManager = tokenManagerMock};
// Act:
subscriber.Subscribe(It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>());
// Assert:
Mock.Get(tokenManagerMock).Verify(x =>
x.GetToken(It.IsAny<string>(), It.IsAny<bool>()), Times.AtLeastOnce);
Read more about verification in Moq at:
Moq quick start at official website
Verifying the Number of Calls to a Mocked Method at BlackWasp
You can verify using MOQ using the Verify method. Like this:
var tokenManagerMock = new Mock<ITokenManager>();
var sut = new WhateverItIsCalled(tokenManagerMock.Object);
sut.Subscribe("ssss", "example#example.com", "XXX");
tokenManagerMock.Verify(m => m.GetToken(It.Is<string>(c => c == "ssss", It.Is<bool>(x => x == false)), Times.Once);
You need to be able to pass the token manager into your system under test somehow. Usually via the ctor or maybe a property.
I would suggest you use something like AutoFixture to remove the ugliness that is "ssss" and make things a bit more DRY.
You may need to make the token manager mock return something appropriate too that will pass the validation. Something like this:
var tokenManagerMock = new Mock<ITokenManager>();
tokenManagerMock.Setup(m => m.GetToken(It.Is<string>(x => x == "ssss", It.IsAny<bool>()).Returns("XXXXXX");

How do I verify a method was called?

I have a ICreateService class that has dependency on ITicketApiAdapter. I've tried registering a mock ITicketAdaper so that it gets injected when I create an anonymous create service.
So, in setup, I have this register for the ticket adapter:
Fixture.Register(() =>
{
var ticketApiAdapter = new Mock<ITicketApiAdapter>();
ticketApiAdapter
.Setup( x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()))
.Returns(new SaveResult
{
Success = true,
Id = Fixture.CreateAnonymous<Guid>().ToString()
});
return ticketApiAdapter;
});
Fixture.Register(() => new CreateService(Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>().Object));
From my understanding, that should "freeze" both the ICreateService and Mock<ITicketApiAdapter> so that when I request an anonymous instance, it's the one I registered.
I have a test that looks like this:
[TestMethod]
public void CreateServiceCallsAddTicketComment()
{
var apiTicketAdapter = Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>();
var createTicketRequest = Fixture.CreateAnonymous<CreateTicketComment>();
var createService = Fixture.CreateAnonymous<CreateService>();
var results = createService.CreateTicketComment(createTicketRequest);
apiTicketAdapter
.Verify(x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()),
Times.Once());
Assert.IsTrue(results.All(x => x.Success));
Assert.IsTrue(results.All(x => x.Errors.Count == 0));
}
I expect the apiTicketAdapter to be the one I registered so that I can verify the method is called. If I step through, the TicketApiAdapter is called, but Moq says it wasn't.
Edit
This is the error I get:
CreateServiceCallsAddTicketComment threw exception:
Moq.MockException: Expected invocation on the mock once, but was 0
times: x => x.AddTicketComment(It.IsAny(), It.IsAny(),
It.IsAny())
Configured setups: x => x.AddTicketComment(It.IsAny(),
It.IsAny(), It.IsAny()), Times.Never No
invocations performed.
When you Register a code block, that code block is going to be invoked every time the Fixture instance resolves the requested type. This means that it's not frozen. If you want to Freeze something, one of the Freeze overloads are often easier to use.
Better yet, since you seem to be using Moq, may I suggest using the AutoMoq extension?
That would enable you to rewrite the test to something like this:
[TestMethod]
public void CreateServiceCallsAddTicketComment(new AutoMoqCustomization());
{
var fixture = new Fixture().Customize()
var apiTicketAdapter = fixture.Freeze<Mock<ITicketApiAdapter>>();
ticketApiAdapter
.Setup( x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()))
.Returns(new SaveResult
{
Success = true,
Id = Fixture.CreateAnonymous<Guid>().ToString()
});
var createTicketRequest = fixture.Freeze<CreateTicketComment>();
var createService = fixture.CreateAnonymous<CreateService>();
var results = createService.CreateTicketComment(createTicketRequest);
apiTicketAdapter
.Verify(x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()),
Times.Once());
Assert.IsTrue(results.All(x => x.Success));
Assert.IsTrue(results.All(x => x.Errors.Count == 0));
}
That's assuming that CreateTicketRequest uses Constructor Injection or Property Injection.

Categories