I am trying to test the below method using RhinoMocks and MbUnit however I am unable to get the test to pass. The current error is when the expect call for "" is not found.
The function is in vb.net and the test is in c#
Public Function Login(user As Website.BusinessObjects.User) As Integer Implements IActivityLog.Login
Dim item As BOAudit.IActivityLog = New BOAudit.ActivityLog(_request)
' Activity
item.UserID = User.GuidID
item.Type = Enums.ActivityType.Login
item.Description = String.Format(If(IsAdmin, "Logged in as {0}", "Logged in"), User.FullName)
item.EventUserID = _authenticatedUser.GuidID
Return _dalActivityLog.Save(item)
End Function
The test below is what I currently have and I believe the issue is down to declaring a new object within the function above and not passing that object into the function. What is the best way to test the above function and should I be passing in the object?
[Test]
public void Login_Data_NewRecordCreated()
{
const int id = 99;
var data = new Website.CodeModules.BusinessObjects.Audit.ActivityLog(_request)
{
Type = Enums.ActivityType.Login,
Description = "Logged in",
EventUserID = _user.GuidID
};
var user = _mocks.StrictMock<User>();
using (_mocks.Record())
{
Expect.Call(_dalActivityLog.Save(data)).Return(id);
}
using (_mocks.Playback())
{
var result = _balActivityLog.Login(user);
Assert.AreEqual(id, result);
}
}
The condition you assert in your test does not seem to have much sense. Your code seems to test that the mock instance in _dalActivityLog returns the constant that you've set up.
In that test you should test the code of the function Login, not the _dalActivityLog implementation. Thus, you should check that _dalActivityLog.Save is called with the right parameter passed.
I suppose that _dalActivityLog is an instance of a class that implements an interface that you haven't specified in your question. Let's call it IActivityLog. Then you should set up a mock instance of it in your test code.
IActivityLog logMock = MockRepository.GenerateStub<IActivityLog>();
Then you inject somehow this mock instance into the instance of the class the has the Login method (via constructor or property).
Then call your Login method and pass there an instance of User.
Then you make the assertion about the _dalActivityLog.Save call, like the one below.
logMock.AssertWasCalled(
call => call.Save(
Arg<Website.CodeModules.BusinessObjects.Audit.ActivityLog>.Matches(
logItem => logItem.UserID == user.GuidID && logItem.Type == Enums.ActivityType.Login
)
)
);
Related
I have created a unit test method that verifies method is called, below is the code for the same.The method builds email object and calls GeneratePDF method which returns bytes further BuildEmailInfo method returns email object.
public class SMTPEmailSender : IEmailSender
{
private IPDFCreater _pdfCreater;
public SMTPEmailSender(IPDFCreater pdfCreater)
{
_pdfCreater = pdfCreater;
}
public Email BuildEmailInfo(string sMTPServerUrl, FaxMailDTO faxAsMailRequest)
{
Email email=null;
try
{
var otp = new PDFData { OTP =faxAsMailRequest.OTP};
email = new Email
{
SMTPServerUrl = sMTPServerUrl,
Encoding = Encoding.UTF8,
ToAddress = faxAsMailRequest.ToEmailAddress,
ToAddressDisplayName = faxAsMailRequest.ToAddressDisplayName,
FromAddress = faxAsMailRequest.FromEmailAddress,
Subject = faxAsMailRequest.Subject,
Body = faxAsMailRequest.Body,
FromAddressDisplayName = faxAsMailRequest.FromAddressDisplayName,
ContentStream = new MemoryStream(_pdfCreater.GeneratePDF(otp)),
AttachmentName = faxAsMailRequest.FaxFileName
};
}
catch(Exception ex)
{
Log.Error("Method : BuildEmailInfo. Exception raised while building email data : {#Message}", ex.Message, ex);
}
return email;
}
Below is my unit test code , whenever I execute this it throws an error Expected invocation on the mock at least once, but was never performed: x=>x.GeneratePDF(pdfdata). Also Let me know if it is right way to perform the test
public class SMTPEmailSenderTest
{
private SMTPEmailSender _sMTPEmailSender;
Mock<IPDFCreater> _mockPdfCreator;
public SMTPEmailSenderTest()
{
_mockPdfCreator = new Mock<IPDFCreater>();
_sMTPEmailSender = new SMTPEmailSender(_mockPdfCreator.Object);
}
[Theory]
[MemberData(nameof(GetFaxAsMailObject))]
public void BuildEmailInfoTest_ReturnsValidEmailObject(FaxMailDTO faxMailDTO)
{
string smpturl = "localhost";
var otp = new PDFData { OTP = faxMailDTO.OTP };
var result = _sMTPEmailSender.BuildEmailInfo(smpturl, faxMailDTO);
_mockPdfCreator.Verify(x => x.GeneratePDF(otp));
}
}
This line:
_mockPdfCreator.Verify(x => x.GeneratePDF(otp));
performs a 'verification'. This is an assertion that checks if method .GeneratePDF has been called on _mockPdfCreator with otp as its parameter.
All .Verify methods from the interface of the Mock object are used to check if some method or property were called. You can also provide some filters to see if certain parameters were passed, for example:
_myMock.Verify(x => x.FooBar(5));
_myMock.Verify(x => x.FooBar(123));
_myMock.Verify(x => x.FooBar(It.IsAny<int>());
_myMock.Verify(x => x.FooBar(It.Is<int>(number => (number-5)%3 > 10));
all of these check if FooBar was alled on _myMock, but each of them looks only at calls that used certain values of parameters: 5, 123, anything-that-is-int, or (...).
You cannot use .Verify to check for the return value.
There's no such option there.
Why? Think about it. You've had:
_mockPdfCreator = new Mock<IPDFCreater>();
....
_mockPdfCreator.Verify(x => x.GeneratePDF(otp));
The _mockPdfCreator is your mock object. Not a real thing. It's a tiny ghost that acts as if it were some IPDFCreater.
There's not a slightest bit of a real implementation there.
How can you expect that GeneratePDF returns anythin meaningful?
It just won't. Nothing's there behind it. If anything called that method GeneratePDF, it would return NULL (or throw exception, depending on mocking mode: Loose/Strict).
...unless you SET UP your mock to do it differently:
var theThing = ...;
_mockPdfCreator = new Mock<IPDFCreater>();
_mockPdfCreator.Setup(x => x.GeneratePDF(It.IsAny<...>())).Returns(theThing);
....
// ... now check what `GeneratePDF` returned?!
Now of anything calls GeneratePDF method, it will return theThing. Alright.
But you knew that already. There's nothing to check. You set up GeneratePDF to return the thing, so there's not a slightest point to check what GeneratePDF returned. It's your mock and your setup!
Sooo, if anything called GeneratePDF, then NULL would be returned, because there's no setup for GeneratePDF. However, as Verify proved, the GeneratePDF was never called. This means that when you created the SMTPEmailSender giving it the mock as parameter:
_mockPdfCreator = new Mock<IPDFCreater>();
_sMTPEmailSender = new SMTPEmailSender(_mockPdfCreator.Object);
and then in test you've had:
....
var result = _sMTPEmailSender.BuildEmailInfo(smpturl, faxMailDTO);
_mockPdfCreator.Verify(x => x.GeneratePDF(otp));
then, apparently, the _sMTPEmailSender.BuildEmailInfo didn't fancy calling GeneratePDF at all.
Why? No idea. Most probably there was something either in smpturl or faxMailDTO that was considered invalid for this use case and that generate-pdf step was skipped. Check the Result. See if there are any errors or messages that would tell you anything about why it did not even try to call GeneratePDF.
Also note that the verification you wrote were
x => x.GeneratePDF(otp)
That's pretty specific. It has hard-coded reference to otp. So maybe it was called, but with different parameter value?
Try adding:
var result = _sMTPEmailSender.BuildEmailInfo(smpturl, faxMailDTO);
_mockPdfCreator.Verify(x => x.GeneratePDF(It.IsAny<PDFData>())); // <-
_mockPdfCreator.Verify(x => x.GeneratePDF(otp));
or something along the lines and see which Verify fails. If the former passes and the latter fails, than everything's mostly fine, it's just not the exact OTP that you expected (maybe _sMTPEmailSender cloned it? etc).
In any chance that the former fails, then it means that GeneratePDF is truly not called even a single time, and then it means you have to learn why BuildEmailInfo with params (smpturl, faxMailDTO) doesn't do what you expect. You've got a try-catch-log there. Maybe some nullreferenceexption? But I doubt it.
You've got there:
[MemberData(nameof(GetFaxAsMailObject))] /// <==== B
public void BuildEmailInfoTest_ReturnsValidEmailObject(FaxMailDTO faxMailDTO) // <--- A
{
...
var otp = new PDFData { OTP = faxMailDTO.OTP }; //<--- C
...
_mockPdfCreator.Verify(x => x.GeneratePDF(otp)); //<---D
So, the faxMailDTO is from GetFaxAsMailObject. The BuildEmailInfo gets it via params and passes part of it to GeneratePDF. Then you assert in Verify that D uses newly-constructed otp from line C. That just can't work. The faxMailDTO from A+B so from GetFaxAsMailObject certainly DOES NOT contain otp from C and certainly will not pass otp object to GeneratePDF. The GeneratePDF will get some other PDFData object that came from faxMailDTO from A+B.
I think I've said enough and covered all issues with your test setup.. You almost have it right. Good luck!
Verifications on mock objects should be your 'last resort' in unit tests. Think about it: is an actual requirement violated if the PDF creator does not call the GeneratePDF method? The user only cares that the PDF was generated.
In this case, you can verify the outcome of the BuildEmailInfo method directly, for example:
var result = _sMTPEmailSender.BuildEmailInfo(smpturl, faxMailDTO);
var expectedBytes = ...; // TODO - get the expected byte[] array from somewhere
Assert.Equal(expectedBytes, result.ContentStream.ToArray());
Additionally, you may be able to write this test without mocking the dependency at all? If the actual PDF creator object can be called to generate a byte[] array in memory, you could just use the real object instead of mocking it.
It is possible to test if a method has been called using Moq and dependency injection. However, is it possible to test if one method in a class calls another within the same class?
For example, I want to test that if I log a certain exception, that an information message is logged as well.
The method is:
public void Error(string message, Exception exception, long logId = 0)
{
var int32 = (int)logId;
Info("Id was converted to an int so that it would fit in the log: " + logId, int32);
Error(message, exception, int32);
}
This was my attempt at unit testing it. The test fails, is there any way that it can it be done?
void logging_an_error_with_a_long_id_also_logs_info()
{
var mock = new Mock<ILogger>();
var testedClass = new Logger();
var counter = 0;
testedClass.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue);
mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>()));
}
Since the Info and Error methods are in the same class (ClassA), I don't believe I can pass ClassA as a dependency into ClassA. So does it not need tested?
The best you're going to be able to do is to make Info virtual. This will allow you to create a Mock<Logger>, set CallBase = true, and verify that Info was called.
var mock = new Mock<Logger>
{
CallBase = true
};
mock.Object.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue);
mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>()));
This way, you're still calling the actual implementation of Error, but you've used Moq to verify the Info method was called.
It feels like you're trying to test the wrong thing. It's not really important that the Info method on your class is called from the Error method, what's important is that the behaviour of the Info method occurs. How it happens is an implementation detail of the class.
If I had a math class with two functions:
public int Mult(int x, int y) {
return x*y;
}
public int Sqr(int x) {
return Mult(x,y);
}
I wouldn't test that calling Sqr called out to the Mult function, I would test Sqr(4)==16. It doesn't matter if that calculation takes place in the Sqr method, or in another method of the class.
Whilst #Andrew's solution is probably what you're after, mocking the class you're testing tends to lead to tightly coupled, brittle tests.
If it's impractical to test the call by observing it's side effects, then it may be a sign that the implementation could use a bit of refactoring.
I'm currently Moq'ing - or attempting to Moq - a class that would insert data into a database.
I am mocking two interfaces and through the use of DI setting them to the constructor of the following 'Facade' class.
Currrently all of my tests run and pass, but I need some guidance on how I can set the returned bool value of the shown 'SaveServiceMessage' method.
Currently I call the 'SynchEmployee' method which is void, internally within this method the 'SaveServiceMessage' is called. Within SaveServiceMessage, I am calling the mocked object method of the constructor 'SaveMessage', this is the method that would be accessing the database in the real non-Moq'd object..
What I need to know, is how I can Moq and get the boolean true or false value of the 'SaveServiceMessage'. I'm new to Moq'ing so hopefully you guys can guide me.
This is my current test:
[Test]
public void TestSynchroniseEmployeeMethod()
{
var employee = new Employee();
{
employee.AOID = "A1";
employee.ID = 1;
}
var guid = Guid.NewGuid();
var serviceClientMock = new Mock<IService>();
var serviceMessageReposMock = new Mock<IServiceMessageRepos>();
var TestFacade = new Facade(serviceClientMock.Object, serviceMessageReposyMock.Object);
TestFacade.SynchroniseEmployee(employee, guid);
serviceMessageReposMock.Verify(x => x.SaveMessage(It.IsAny<ServiceMessage>()), Times.Exactly(1));
serviceClientMock.Verify(x => x.SendServiceMessage(It.IsAny<ServiceMessage>(), It.IsAny<string>()), Times.Exactly(1));
}
public class Facade
{
IService _serviceMessage;
IServiceRepos _serviceMessageRepos
public Facade(IService serviceMessage, IServiceRepos serviceMessageRepos)
{
_serviceMessage = serviceMessage;
_serviceMessageRepos = serviceMessageRepos;
}
public bool SaveServiceMessage(ServiceMessage message, Guid correlationId, ConversationStatus status)
{
if (message != null)
{
message.CorrelationID = correlationId;
_serviceMessageRepos.SaveMessage(message);
return true;
}
return false;
}
public void SynchEmployee(Employee employee, Guid messageId)
{
var employees = new List<Employee>();
employees.Add(employee);
var message = new ServiceMessage(employee.ID, null, ServiceMessageType.EmployeeSyncRequest, Guid.NewGuid());
message.ID = employee.ID.ToString();
SaveServiceMessage(message, message.CorrelationID, ConversationStatus.NEW);
TransmitServiceMessage(message);
}
}
SynchEmployee() takes in an Employee and a Guid (messageId) and calls IServiceRepos.SaveMessage() on a message. There seem to be no options, so the single test should suffice but...
We do not check anything about the saved message...
Should the saved message be using the messageId? We do not check that it is - it is not, we create a new id when creating the message. If the saved message should contain the passed in messageId then the verify should check this.
Was the employee Id read from the Employee and put into the message (it seems to be used twice, once in the ctor, once afterwards)
Is the message type correct?
There is a verify in the test for SendServiceMessage() which is never called.
We add the employee to a local list of employees and then do nothing further with it.
We set the message id to the employee id - is this correct? If yes, then why are we passing in the messageId?
In the ctor of ServiceMessage() we pass in a newly created GUID and then set the ID of the message to the employeeId. Is the last parameter on the ctor the ID. if so, can we pass in the value at this point instead of setting it afterwards.
Personal preference: Having the new ServiceMessage(...) call does some damage to the testability. If we passed in a service to create the message then we could just verify that the service was called with the correct parameters and return a dummy message that we can use in the verify calls instead of having to write comparators for the message.
We pass a ConversationStatus into SaveServiceMessage() that is never used.
I think you are looking for something like this:
serviceMessageReposMock.SetUp(x => x.SaveServiceMessage(It.IsAny<ServiceMessage>(), GUId, status)).Returns(true);
This way the SaveServiceMessage will not get actually called, but still can verify the output.
I'm trying to create some unit tests for an application I've recently inherited. Currently using NSubstitute because that's what the previous programmer used, but I'm not attached to it.
The method I'm testing calls the DataService class' Create method.
Calling Create Method
var contactProductLink = this.dsService.Create<ContactProductLink>(x =>
{
x.ContactRoleId = prod.RoleId;
x.ContactId = contactViewModel.ContactId;
x.ProductId = prod.ProductId;
x.Active = true;
x.InsertDate = DateTime.Now;
x.InsertUserId = user.employeeId;
x.UpdateDate = DateTime.Now;
x.UpdateUserId = user.employeeId;
});
DataService Create Method:
public TEntity Create<TEntity>(Action<TEntity> propertySetter = null) where TEntity : class
{
var tEntity = this.Context.Create<TEntity>();
if (propertySetter != null)
{
propertySetter(tEntity);
}
return tEntity;
}
The approach I've taken (and maybe there's a better way) is to use NSubstitute to mock the DataService. When I'm doing my assertions at the end, I'm checking to make sure that the Create method was called:
mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());
However, I'd like to also verify the input that was sent to the method is correct, and here's where I'm running into trouble. I can get the System.Action object that was passed to the Create method, but I can't figure out how to pull out the parameters (such as ContactRoleId, ContactId, etc. as posted in the calling create method code snippet).
So after all of that what I'm asking is:
How can I access those input parameters so I can verify the correct arguments are being passed to the data service? Is it even possible?
Is there a better way to do this than what I'm currently trying to do?
Solution
//Arrange
mockDataSupplierService.Create<ContactProductLink>(Arg.Do<Action<ContactProductLink>>(x=> actionToPopulateEntity = x));
//Assert
mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());
var entity = new ContactProductLink();
actionToPopulateEntity.Invoke(entity);
Assert.AreEqual(ExpectedContactId, entity.ContactId);
How can I access those input parameters so I can verify the correct arguments are being passed to the data service? Is it even possible?
Essentially you can't, as it is not possible to extract "code" details from action (consider what happens when you pass an action that doesn't set any properties - this is totally legal, but would break hypothetical mechanism).
However, you can try this instead:
Create entity with initial values
Use Arg.Invoke argument, telling NSubstitute to use chosen object as action parameter
Verify that entity properties values changed
For example:
// Arrange
var entity = new ContactProductLink
{
ContactRoleId = // ...
// ...
};
mockDataSupplierService
.Create<ContactProductLink>(Arg<ContactProductLink>.Invoke(entity));
// Act
// ...
Assert.That(entity.ContactRoleId, Is.EqualTo(2));
// ...
I have the following code:
var service = new Mock<INavigationService>();
service.Setup(x => x.GetSchemes(new SchemeFilterEntity())).Returns(new List<SchemeEntity>
{
new SchemeEntity
{
Id = 1,
Name = "Test"
},
new SchemeEntity
{
Id = 2,
Name = "Test 2"
}
});
var sut = service.Object;
var sut = service.GetSchemes(new SchemeFilterEntity());
However when the GetSchemes method is called it returns null?
Any ideas?
I believe that should be
service.Setup(x => x.GetSchemes(It.IsAny< SchemeFilterEntity >())).Returns.....
because otherwise, moq will be looking for that exact instance of the 'new SchemeFilterEntity()' that you passed in in the setup method, which will never match anything else.
Edit: That said, your sut should not be the thing you are mocking, it should be the thing that's using your mocked object.
I don't know what you are tring to test but if you want "Override" the behavior of GetSchema
using a mocked object that method must be virtual on the class
If you want to use the mocked object to stub out the INavigationService you have to do the below
.........
var sut = service.Object;
SomeThing.UseNavigavtionService(sut); //this is supposed to be the class which you will test.Sut is a mocked INavigationService
in your setup you should also use It.IsAny< SchemeFilterEntity >() instead of create a concrete object