API testing using post man - testing

I am new to api testing from postman.I went through several blogs and articles on
api testing.But I don't know how deeper we can done testing.
Also how can we write test for post request.I have the below department mode class
from my web api.
[Key]
public int DepartmentId { get; set; }
[Required]
[Display(Name ="Department Name")]
public string DepartmentName { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
The sample get request i used is given below
var body = JSON.parse(responseBody);
if(!body.DepartmentId)
{
tests["department id must exists in response"]=true;
}
else
{
tests["department id exists in response"]=true;
}
if(typeof body.DepartmentName !='string')
{
tests["department name must be type string"]=true;
}
if(responseCode.name.has("OK"))
{
tests["Status code name has string OK"] = true;
}
Whether the above testing procedure is correct.?
What all things to be tested while invoking a post request and get request against department controller for the above model.

You dont have to write 2 test cases to test for +ve and -ve scenario. All you need to do is write one test case and it will either pass or fail based on the scenario. For example lets consider your DepartmentId
The test case should be
tests["department id must exists in response"]= body.DepartmentId? true : false;
Based on whether you department id exists or not either your test case will pass (marked green) or fail (marked red).
Alternatively if you are dealing with not only testing but also designing your APIs and documenting them then have a look at http://myapic.com. Its a great tool for end to end API design documenting and testing.

Related

FluentAssertions GraphComparison, all properties of only output object should be filled

Often in my team people forget to map certain fields from an input object to an output object. I wanted to write a library for unit testing, that checks if all properties on an output object have been filled with a value different than the default value, if not, an exception should be thrown. Ofcourse certain properties will need to be able to be excluded.
I noticed that Fluent Assertions can already do this with the .Should().BeEquivalentTo() Graph comparison.
However, I when a property is not present on the input object, I run into some trouble. Given the following objects:
public class Input
{
public int Age{ get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Output
{
public int Age { get; set; }
public string FullName{ get; set; }
public static Output CreateFrom(Input i)
{
return new Output
{
Age = i.Age,
FullName= $"{i.FirstName} {i.LastName}"
};
}
}
When I do the following assertion:
var input = new Input
{
Age = 33,
FirstName = "Foo",
LastName = "Bar"
};
var output = Output.CreateFrom(input);
var fullName = $"{input.FirstName} {input.LastName}";
input.Should().BeEquivalentTo(output,
o => o.Using<string>(i => i.Subject.Should().Be(fullName)).When(
info => info.Path.Contains(nameof(output.FullName)))
);
I get an exception that FullName is not a property on the Input object, which is fair, but I can't use .Excluding(o => o.FullName) in this case because that would skip assertion all togheter.
I could use .Excluding(o => o.FullName), and write a seperate assertion below it as follows:
output.FullName.Should().Be(fullName);
but that doesn't fix the problem I'm trying to solve, I want every property to be mapped, OR have a specific assertion in BeEquivalentTo so people don't forget to write mappings. And they can still forget to write this seperate assertion when they add .Exluding.
The .WithMapping<Input>() extension method will also not work, since you can assign one property on the input, to another property on the output, but doesn't account for the scenario described above.
IS there a way to do this with Fluent Assertions? That would be my preference since it's already included in the project. Are there anylibraries that tackle this specific scenario, or am I going to have to write this myself?
Thanks!

Azure QnaMaker chat logs are not generated

The GenerateAnswer API describes userId if sent in a request will be recorded in chat logs which as far as I could see do not seem to get generated.
Do chat logs get generated by default? or am I required to provision resources or make configuration changes for logging to take effect?
And please can you point me to Azure documentation if any that describes the logging aspects of QnA Maker in detail?
Thanks
QnA Maker does not generate chatlogs by default. They currently do not offer any APIs to store chat logs.
Assuming you are using it in a form of a chatbot where question and answers are displayed concurrently, you could create a database instance that is stored locally such as SQL Server 2016.
Then by generating a unique GUID based on time of user visit store each chatlog in a table with the Primary key as 'GUID' followed by 'Question' and 'Answer' and 'Time'.
Example of potential answer model
namespace Frontend.Data {
public class Message {
[Key]
public string MessageId { get; set; }
public string ConversationId { get; set; }
public string Question { get; set; }
public string Answer { get; set; }
public DateTime MessageReceivedAtDateTime { get; set; }
public Message(string messageId, string conversationId, string question, string answer, string datestring) {
MessageId = messageId;
ConversationId = conversationId;
Answer = answer;
Question = question;
MessageReceivedAtDateTime = DateTimeOffset.Parse(datestring).UtcDateTime;
}
public Message() {}
}
However, you may have to tinker around with saving the question and answers as the user exits the program.
Depending on the language you are implementing QnA Maker, you may need to tweak some of these changes
https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/sql-server-2016-express-localdb?view=sql-server-2017
https://learn.microsoft.com/en-us/dotnet/api/system.guid.newguid?view=netframework-4.7.2

How does abstractions help in DRY?

When we search "Don't repeat yourself" on Wikipedia, the first sentence is:
In software engineering, don't repeat yourself (DRY) is a principle of
software development aimed at reducing repetition of software
patterns, replacing them with abstractions...
I know that abstractions in software engineering mean hiding implementation complexity of how the behaviors of an API are realized, but it seems that "abstractions" in this sentence is not what I know before. Could someone explain to me what abstraction means here? It would be better if you could give me an example.
I know that abstractions in software engineering mean hiding
implementation complexity of how the behaviors of an API are realized
Yes it means that (absstraction#wikipedia) and very same concept can also be leveraged to reduce repetitions! Or in other words, it can be used to practice DRY.
Let me try to explain that with an example. First I'll show non DRY code (without abstraction), then with use of abstraction I'd try to reduce repetitions.
Let's assume that you wanted to build an email view model based on application form details filled out by applicant and there is an email view class which consumes this emailViewModel to show all non-null details from application form. You could write it like in below example (first attempt)
public class ApplicationForm
{
public AddressDetail AddressDetail { get; set; }
public CustomerDetail CustomerDetail { get; set; }
public ProductDetail ProductDetail { get; set; }
}
public class EmailViewModel
{
public EmailViewModel(ApplicationForm applicationForm)
{
Address = GetAddressDetail(applicationForm.AddressDetail);
Customer = GetCustomerDetail(applicationForm.CustomerDetail);
Product = GetProductDetail(applicationForm.ProductDetail);
}
public string Address { get; set; }
public string Customer { get; set; }
public string Product { get; set; }
}
//view code assume razor view
#if(Model.Address!=null)
{
// method for showing address
}
#if(Model.Customer!=null)
{
// method for showing customer
}
//and other properties
I've kept above code quite simple; only three properties and haven't showed declaration for conversion methods. What if there were 50 properties! In this first approach it would be cumbersome changes that you'd be making in three places. Now I'll show you second example code of how you could create an interface (a way of abstraction) implement DRY.
interface IFormDetail
{
IFormDetailView GetDetail();
}
interface IFormDetailView
{
string ShowView();
}
public class ApplicationForm
{
public List<IFormDetail> FormDetails {get;set;}
}
public class EmailViewModel
{
public EmailViewModel(ApplicationForm applicationForm)
{
if(applicationForm.FormDetails!=null)
{
FormDetails = new List<IFormDetailView>();
foreach(var detail in applicationForm.FormDetails)
{
FormDetails.Add(detail.GetDetail());
}
}
}
public List<IFormDetailView> FormDetails { get; set; }
}
//view code assume razor view
#f(Model.FormDetails!=null)
{
foreach(var detail in Model.FormDetails){
detail.ShowView();
}
}
In this second code example , when you've a new property, you'll only make one change when a new application form property is created.
So while we are hiding complexity of how detail is presented etc., we are also leveraging it to reduce repetition.

MVC4 WebApi OData Delta<T> is not populating GUIDs or Int fields

I'm looking to do partial updates on a web api controller action by using the Delta wrapper.
I have a model like such:
public class Person
{
public Guid PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsActive { get; set; }
public int NumVacationDays { get; set; }
public double Salary { get; set; }
}
I have the api controller like such:
public void Put(Delta<Person> person)
{
var p = person.GetEntity();
Person existingPerson = _repository.Get(p.PersonId);
person.Patch(existingPerson);
_repository.Update();
return;
}
I make the call to the web api like such (using fiddler)
url: http://localhost:49933/api/Person (PUT)
Response Body
{
"PersonId": "b269c49f-8a90-41d6-b102-7cfba3812b1c",
"FirstName": "sample string 2",
"LastName": "sample string 3",
"IsActive": true,
"NumVacationDays": 5,
"Salary": 6.1
}
The controller is hit and al
l the data is populated other than the NumVacationDays (which is 0) and the PersonId (which defaults to 00000000-0000-0000-0000-000000000000)
Does anyone know why the GUIDs and int fields are not populating from the json?
This problem is mentioned in this bug: http://aspnetwebstack.codeplex.com/workitem/562 ...Claims to be fixed but still exists in the 4.0 just released.
The problem being that Newtonsoft Json deserializes a number as Int64 which fails test that IsAssignable to an int, and so it is skipped. Similar issue for guids as strings.
You are supposed to be able to fix this by using the OData media type formatters, which are enabled by deriving from ODataController instead of ApiController. However this had no effect for me - int values still do not work (but when I change the data type to Int64, it works).
I would love to see a working example of posting json with a patch delta that contains an int.
I can venture a guess for what is happening with PersonId but NumVacationDays cannot be explained. My guess is that PersonId is the key property for the Person entity and by default the ODataFormatter does not patch key properties. If you want that behavior, you can change the setting on ODataMediaTypeFormatter.PatchKeyMode to Patch.
Also, it would be interesting to see the value of person.GetChangedPropertyNames() in the action to see if PersonId and NumVacationDays actually show up there or not.

How to auto-load details (with conditions) associated with an entity using Ria Services?

I'm developing a project using Silverlight 4 and Entity Framework 4 and I'm trying to auto-load the details (with conditions) associated with an entity when the client loads the EntityQuery.
So far, I've been able to put in place a solution, using the Include attribute, that returns all the details associated with the master entity. What I'm missing here is to be able to filter out the details based on some criteria.
As an example, here's what my entities look like:
Entity Movie
Id (int)
[Include]
MovieLocalizedInformations (EntityCollection<MovieLocalizedInformation>)
Entity MovieLocalizedInformation
Id (int)
Movie_Id (int)
LanguageCode (eg.: en)
Title
On my DomainService object, I expose the following method:
public IQueryable<Movie> GetMovies( string languageCode )
{
return this.ObjectContext.Movies.Include( "MovieLocalizedInformations" );
}
This works fine. But when I try to add where clause to filter out the localized information based on the language code, only the movies get loaded on the client.
Is there a way to achieve the filtering in one query?
Note: I'm also using the DomainDataSource with paging on the client so the solution needs to work with that.
Any help would be greatly appreciated!
Thanks,
Jacques.
Not sure about Enitity Framework but with a LinqToSqlDomainService you use the LoadWith loadOption
to include the details entities and then use the AssociateWith LoadOption to filter the detail e.g
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<Movies>(i => i.MovieLocalizedInformations);
options.AssociateWith<Movies>(i => i.MovieLocalizedInformations.Where(d=> myListOfIds.Contains(d.LocationId)));
Ok,
For efficiency reason, I decided to go with custom DTO object that fetches the localized information and flatten the result.
But, the same problem occurred when my custom DTO needed to reference another custom localized DTO.
Here is how I came to do the same as the .Include( "PropertyName" ) that the ObjectSet offers:
Entity LocalizedMovieCollection
public class LocalizedMovieCollection
{
[Key]
public int Id { get; set; }
public string Name { get; set; } (the result of a sub query based on the language)
[Include]
[Association( "LocalizedMovieCollection_LocalizedMovies", "Id", "MovieCollection_Id" )]
public IEnumerable<LocalizedMovie> Movies { get; set; }
}
Entity LocalizedMovie
public class LocalizedMovie
{
[Key]
public int Id { get; set; }
public string Name { get; set; } (the result of a sub query based on the language)
public int MovieCollection_Id { get; set; }
[Include]
[Association( "LocalizedMovie_LocalizedMovieCollection", "MovieCollection_Id", "Id", IsForeignKey = true]
public LocalizedMovieCollection MovieCollection { get; set; }
}
Then, I've declared two methods: One that returns an IQueryable of LocalizedMovieCollection and the other, an IQueryable of LocalizedMovie. (Note: There must be at least one method that returns each type of entity for the entity to get auto-generated on the Silverlight client)
My goal is to automatically load the MovieCollection associated with a Movie so the method definition to get the movies is as follow:
public IQueryable<LocalizedMovie> GetMovies( string languageCode )
{
return from movie in this.ObjectContext.Movies
join movieLocalizedInfo in this.ObjectContext.MovieLocalizedInformations
on movie equals movieLocalizedInfo.Movie
join movieCollection in this.ObjectContext.MovieCollections
on movie.MovieCollection equals movieCollection
join movieCollectionLocalizedInfo in this.ObjectContext.MovieCollectionLocalizedInformations
on movieCollection equals movieCollectionLocalizedInfo.MovieCollection
where movieLocalizedInfo.LanguageCode == languageCode && movieCollectionLocalizedInfo.LanguageCode == languageCode
select new LocalizedMovie()
{
Id = movie.Id,
Name = movieLocalizedInfo.Name
MovieCollection_Id = movieCollection.Id,
MovieCollection = new LocalizedMovieCollection(){ Id = movieCollection.Id, Name = movieCollectionLocalizedInfo.Name }
}
}
When the Silverlight client loads the query, all the LocalizedMovies and their associated LocalizedMovieCollections will be loaded into the context.