Unit Testing - dependency injection zf2 - unit-testing

In one of controller I have following code to send email and sms using dependency injection. which works fine
$message = new \Application\SendMessage\Message();
$message->toName = $toName;
$message->toEmail = $toEmail;
$message->fromEmail = $fromemail;
$message->emailBodyText = $emailBodyText;
$message->smsMessage = $emailBodyText;
$message->toMobile = $toMobile;
$seSMS = new \Application\SendMessage\SendSMS($message);
$suSMS = new \Application\SendMessage\SendMessage($seSMS);
$statusMsg = $suSMS->releaseMsg();
$seEmail = new \Application\SendMessage\SendEmail($message);
$suEmail = new \Application\SendMessage\SendMessage($seEmail);
$statusMsgEmail = $suEmail->releaseMsg();
and I am testing it, using following code
public function testcreateActionCanBeAccessed()
{
$postData = array(
// variables here
);
$this->dispatch('/mycontroller/myaction', 'POST', $postData);
$this->assertResponseStatusCode(200);
}
Which works fine and give me 100 percent code coverage, Only problem is, every time I run unit test, it sends the email and release the sms text message as well. which is good sometimes, as it also tests email sending and text messaging feature.
But if you have to run your test again and again it is kind of annoying, How can I mock above code so it will still give me 100 percent code coverage but will not send sms text and email.

One way would be to utilize the "Service Locator Pattern" http://en.wikipedia.org/wiki/Service_locator_pattern
Instead of:
$message = new \Application\SendMessage\Message();
You would have something like:
$message = $service_locator->new('Application\SendMessage\Message');
In your test, you could then utilize mocking (http://phpunit.de/manual/3.7/en/test-doubles.html) to return "dummy" messages/sendmessages that don't actually send an email, but still ensure the proper methods get called.

Related

SendGrid V3 api with C# not able to send mail from Console Application

I am not able to send email with SendGrid using the V3 API in a console application. It works fine in my Web Application. I created a test console project and used the sample code from the SendGrid site. When the command to send the message is called, the application simply exits. I cannot read any response from the call.
This is in VB.Net. Sorry, I think I am the only person on Earth who codes in VB.
If I execute this code in the sample sendgrid-csharp-main from GitHub, it works fine. I cannot find anything in the sample code that looks any different from my code in the section that actually calls the send message part (other than having to convert to VB).
Does anyone see ANYTHING wrong in this code? I am using the .Net 4.7.2 framework.
This is the entirety of the test code. I have been spinning my wheels searching for help for too long and I am desperate now.
Imports System.Net.Http
Imports SendGrid
Imports SendGrid.Helpers.Mail
Module Module1
Sub Main()
TryIt().ConfigureAwait(True)
End Sub
Private Async Function TryIt() As Task
Dim HttpClient As HttpClient = New HttpClient()
Dim apiKey = "my private api key"
Dim client = New SendGridClient(HttpClient, New SendGridClientOptions With {
.ApiKey = apiKey,
.HttpErrorAsException = True
})
Dim from = New EmailAddress("msie#msinvoiceExchange.com", "MSIE")
Dim subject = "Hello World from the Twilio SendGrid CSharp Library Helper!"
Dim toEmail = New EmailAddress("joe#invoicesanywhere.com", "Joe")
Dim plainTextContent = "Hello, Email from the helper [SendSingleEmailAsync]!"
Dim htmlContent = "<strong>Hello, Email from the helper! [SendSingleEmailAsync]</strong>"
Dim msg As New SendGridMessage With {
.From = from,
.Subject = subject,
.PlainTextContent = plainTextContent,
.HtmlContent = htmlContent
}
msg.AddTo(toEmail)
Dim myResponse As Response
myResponse = Await client.SendEmailAsync(msg)
Console.WriteLine(msg.Serialize())
Console.WriteLine(myResponse.StatusCode)
Console.WriteLine(myResponse.Headers)
Console.WriteLine(vbLf & vbLf & "Press <Enter> to continue.")
Console.ReadLine()
End Function
End Module
It figures. As soon as I get desperate enough to post a question, I figure out something that works.
I just hope that someone else has the same problem and finds this answer helpful.
This is the change I had to make to get this to work
Sub Main()
TryIt().Wait()
End Sub

How do I unit test model validation in controllers decorated with [ApiController]?

As pointed out in this anwer to Asp.Net Core 2.1 ApiController does not automatically validate model under unit test, the automatic ModelState validation that ASP.NET Core 2.1's ApiControllerAttribute gives us only works when actualyy requestion the action at runtime, not by calling it with an invalid parameter in a unit test.
However, I still want to test if my action actually returns a BadRequestResult when supplying an incorrect model. Is there any way of doing this? I get that I can still manually check if ModelState.IsValid is false, and returning BadRequest() myself, but that kind of defeats the point of the automatic validation.
Am I stuck manually checking ModelState.IsValid after all, or is there a way to make use of the new ApiControllerAttribute model validation in a unit test?
If you want to validate that the api's are returning a badrequest when the data annotations are broken then you need to do an api integration test.
One nice option is to run the integration tests via an in-memory client using the TestServer
Here's an example:
//arrange
var b = new WebHostBuilder()
.UseStartup<YourMainApplication.Startup>()
.UseEnvironment("development");
var server = new TestServer(b) { BaseAddress = new Uri(url) };
var client = server.CreateClient();
var json = JsonConvert.SerializeObject(yourInvalidModel);
var content = new StringContent(json, Encoding.UTF8, "application/json");
//act
var result = await client.PostAsync("api/yourController", content);
//assert
Assert.AreEqual(400, (int)result.StatusCode);
If you only need to make sure that the annotations is proper setup you can manually trigger the validation via the TryValidateObject method
var obj = new YourClass();
var context = new ValidationContext(obj);
var results = new List<ValidationResult>();
var valid = Validator.TryValidateObject(obj, context, results, true);

Mocking an Eloquent collection response from another mocked class

I Have looked at many questions along the same line of thought here on stack overflow, and else where but unable to find a solution to this particular issue.
I'm fairly new to Unit Testing in general, so the mistake may be (hopefully) obvious to someone with more experience.
Here's the issue:
I have a ResourceController that injects a class into the constructor using Depedency Injection.
public function __construct(ResourceAPIInterface $api)
{
$this->api = $api;
}
When that API is called in the controller, the class that was injected does some business logic and returns an Eloquent Collection.
public function index($resource, $version)
{
$input = Input::all();
//Populate Data
$data = $this->api->fetchAll($input);
//Format response
if($data->isEmpty()){
//Format response
$response = Response::make(" ", 204);
}else {
//Format response
$response = Response::make($data, 200);
}
//Set content-type in header
$response->header('Content-Type', 'application/json');
$response->header('Cache-Control', 'max-age=3600');
return $response;
}
As you can see from the code above, I need the response to be an eloquent response so i can test to see if it's empty. The method FetchAll literally just returns a Eloquent collation of all records in the table. When I do the test, i'm able to mock the API without issue. However when i'm mocking the response, i really want the response to be an eloquent collection, and having difficulty getting that to work. Here's an example of the test:
$course = Mockery::mock(new API\Entity\v1\Test);
$this->mock->shouldReceive('fetchAll')->once()->andReturn($course->all());
$this->mock->shouldReceive('name')->once()->andReturn('Course');
// Act...
$response = $this->action('GET', 'ResourceController#show');
// Assert...
$this->assertResponseOk();
The above works, but when i want to do the same test against the show method and mock the eloquent response for ->first() I'm getting errors.
1) ResourceControllerTest::testshow
BadMethodCallException: Method Mockery_1_API_Entity_v1_Test_API_Entity_v1_Test::first() does not exist on this mock object
I've tried to test the model by doing:
$course = Mockery::mock('Eloquent', 'API\Entity\v1\Test');
$response = $course->mock->shouldReceive('find')->with(1)->once()->andReturn((object)array('id'=>1, 'name'=>'Widget-name','description'=>'Widget description'));
However when I run that in the Test I get the following error:
1) ResourceControllerTest::testIndex
BadMethodCallException: Method Mockery_1_API_Entity_v1_Test::getAttribute() does not exist on this mock object
Any Ideas on how to resolve this issue? Also, if there's a better way to test if the eloquent collection is empty that might resolve some of the complexity that I'm running into is also welcome.
Ok, I figured out how to make this work:
public function testIndex($resource="course", $version="v1")
{
// Arrange...
$course = Mockery::mock('Eloquent', 'API\Entity\v1\Page')->makePartial();
$course->shouldReceive('isEmpty')->once()->andReturn(false);
$course->shouldReceive('all')->once()->andReturn($course);
$this->mock->shouldReceive('fetchAll')->once()->andReturn($course->all());
$this->mock->shouldReceive('name')->once()->andReturn('Course');
// Act...
$response = $this->action('GET', 'ResourceController#index');
// Assert...
$this->assertResponseOk();
}
I was able to do the PartialMock to get around the getAttribute() Error. Once I did that, I started getting the error:
Call to undefined method stdClass::isEmpty()
So I decided to mock that as well, and pass the whole mocked object into the expected response for the all command.
Then in the mock for the API class $this->mock-> i had it return The mocked eloquent collection with the ->all() method.
This is also working for the other test i had for find($id). That one however didn't require an isEmpty() check so was easier to mock.

MAPI, HrQueryAllRows: Filter messages on subject

I'm pretty much new to MAPI and haven't wrote much C++ Code.
Basically I want to read all emails in the inbox and filter them based on their subject text. So far I'm using the source code provided at the microsoft msdn website which basically reads all emails from the inbox. What I want now is to not get all emails but filter them on the subject, lets say: I want all emails in my Inbox with the subject title "test".
So far I figuered out that the following line of code retrieves all the mails:
hRes = HrQueryAllRows(lpContentsTable, (LPSPropTagArray) &sptCols, &sres, NULL, 0, &pRows);
The parameter &sres is from the type SRestriction.
I tried to implement a filter on 'test' in the subject:
sres.rt = RES_CONTENT;
sres.res.resContent.ulFuzzyLevel = FL_FULLSTRING;
sres.res.resContent.ulPropTag = PR_SUBJECT;
sres.res.resContent.lpProp = &SvcProps;
SvcProps.ulPropTag = PR_SUBJECT;
SvcProps.Value.lpszA = "test";
ScvProps is from the type SPropValue.
If i execute the application then I get 0 lines returned. If I change the String test to an empty String then I get all emails.
I'm assuming i'm using the "filter" option wrong, any ideas?
Edit: When I change the FuzzyLevel to:
sres.res.resContent.ulFuzzyLevel = FL_SUBSTRING;
then I can look for subjects that contain a single character but as soon as I add a second character I get 0 rows as result. I'm pretty sure this is just some c++ stuff that I don't understand that causes all this problems ...
I figured the problem out.
Replacing
sres.res.resContent.ulFuzzyLevel = FL_FULLSTRING;
sres.res.resContent.ulPropTag = PR_SUBJECT;
SvcProps.ulPropTag = PR_SUBJECT;
with
sres.res.resContent.ulFuzzyLevel = FL_SUBSTRING;
sres.res.resContent.ulPropTag = PR_SUBJECT_A;
SvcProps.ulPropTag = PR_SUBJECT_A;
fixed the problem.

How can I verify the output of this method using Moq

I have an MVC3 app and I've got a Register ActionMethod on the AccountController. When a user registers I want it to email them their user details. I'm using Postal (for the first time) and want to run a unit test that verifies that the Send method gets called and that I've called the Register email template.
Here is the section of code in my Register ActionMethod that calls the email tempalte:
dynamic email = new Email("Register");
email.To = model.Email;
_emailService.Send(email);
_emailService is of type IEmailService. I'm using Moq and know how to verify a method has been called but in this instance I'm passing an Email object into Send. So I don't know if I create a Mock or whether the Email object used on the Register controller is what I should be testing. I'm also not sure on the best way to test the 'output' of the email or to at least verify that the 'Register' template in the Views/Emails folder is called. Here's my test so far:
[TestMethod]
public void register_post_success_sends_email_with_account_details()
{
// Arrange
// fakeMembers contains a List<Member> repository of 5 fake Members which I
// use to ensure the Register completes and then steps into the code
// that calls the email code authentication code
FakeMembers fakeMembers = new FakeMembers();
_mockMemberRepository.Setup(x => x.GetMembers()).Returns(fakeMembers.Members);
_mockEmailService.Setup(e => e.Send(?? what do I place here??));
// set up of emailService.Send is a void method so do I just not use Returns?
//// Arrange
Member model = new Member()
{
Email = "member6#mydomain.com",
Password = "test123",
ConfirmPassword = "test123"
};
Mock<Email> mockEmail = new Mock<Email>();
// Act
var result = _controller.Register(model);
// Assert
// Do I use a mockEmail.Object here? I want to test the Email called on the
// Register ActionMethod?
// Test Send method was called ONCE
_mockEmailService.Verify(e => e.Send(mockEmail.Object), Times.Once());
//Test either the output of the Email that was sent OR check that it was the
//Register email template that was called
}
I hope I've been concise enough and someone can help
No need to use Setup on a method that has no return. Since by the looks Email is just a data structure there is no need to mock it. Besides since it get new'ed up inside the controller it is best to verify the object passed into Send has the properties I expect using It.Is<> syntax.
[TestMethod]
public void register_post_success_sends_email_with_account_details()
{
//// Arrange
FakeMembers fakeMembers = new FakeMembers();
_mockMemberRepository.Setup(x => x.GetMembers()).Returns(fakeMembers.Members);
Member model = new Member()
{
Email = "member6#mydomain.com",
Password = "test123",
ConfirmPassword = "test123"
};
//Act
var result = _controller.Register(model);
//Assert
_mockEmailService.Verify(e => e.Send(It.Is<Email>(email =>
{
return email.To == model.Email; // you can add more here such as the body etc
}), Times.Once())
//Test either the output of the Email that was sent OR check that it was the
//Register email template that was called
As for this part I would separate into 2 tests where you know which condition will be met.