Monday, 27 June 2022

ASP.NET Core Integration test using Moq Framework

 Testing coverage is the key part of any project development and Testing coverage is not only about the unit testing instead Integration Testing is extremely important to make sure entire system is unbroken & bug free with any change or subsequent enhancement.

namespace CoreWebAPIMoqDemo.Services
{
public interface IWeatherForecastService
{
Task<WeatherForecast[]> GetWeatherForecast();
}
public record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
}
namespace CoreWebAPIMoqDemo.Services
{
public class WeatherForecastService : IWeatherForecastService
{
string[] summaries = new string[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

public async Task<WeatherForecast[]> GetWeatherForecast()
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateTime.Now.AddDays(index),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
)).ToArray();
return forecast;
}

}
}
using CoreWebAPIMoqDemo.Services;var builder = WebApplication.CreateBuilder(args);// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<IWeatherForecastService, WeatherForecastService>();
var app = builder.Build();// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();app.MapGet("/weatherforecast", async (IWeatherForecastService service) =>
{
return await service.GetWeatherForecast();
})
.WithName("GetWeatherForecast");
app.Run();public partial class Program { }
<PackageReference Include="Moq" Version="4.18.1" />
using Moq;
using CoreWebAPIMoqDemo.Services;
using System.Reflection;
namespace CoreWebAPIMoqDemo.Tests
{
internal class MockServices
{
public Mock<IWeatherForecastService> WeatherForecastServiceMock { get; init; }
public MockServices()
{
WeatherForecastServiceMock = new Mock<IWeatherForecastService>();
}
/// <summary>
/// This returns the collection of all mock service's interface type and the mock object, defined here i.e. <see cref="WeatherForecastServiceMock"/>.
/// </summary>
/// <returns></returns>
public IEnumerable<(Type, object)> GetMocks()
{
return GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Select(x =>
{
var interfaceType = x.PropertyType.GetGenericArguments()[0];
var value = x.GetValue(this) as Mock;
return (interfaceType, value.Object);
})
.ToArray();
}
}
}
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using CoreWebAPIMoqDemo.Services;
namespace CoreWebAPIMoqDemo.Tests
{
internal class TestMoqPOCApplication : WebApplicationFactory<Program>
{
private readonly MockServices _mockServices;
public TestMoqPOCApplication(MockServices mockServices)
{
_mockServices = mockServices;
}
protected override IHost CreateHost(IHostBuilder builder)
{
builder.ConfigureServices(services => {
foreach ((var interfaceType, var serviceMock) in _mockServices.GetMocks())
{
services.Remove(services.SingleOrDefault(d => d.ServiceType == interfaceType));
services.AddSingleton(typeof(IWeatherForecastService), serviceMock);
}

});
return base.CreateHost(builder);

}
}
}
using Moq;
using CoreWebAPIMoqDemo.Services;
using Newtonsoft.Json;
namespace CoreWebAPIMoqDemo.Tests
{
public class WeatherForecastTests
{
private readonly TestMoqPOCApplication _testMoqPOCApplication;
private readonly MockServices _mockServices;
public readonly HttpClient _client;

public WeatherForecastTests()
{
_mockServices = new MockServices();
//instantiating TestMoqPOCApplication
_testMoqPOCApplication = new TestMoqPOCApplication(_mockServices);
//creating client for api call
_client = _testMoqPOCApplication.CreateClient();
}
[Fact]
public async void GetWeatherForecastTest()
{
//mocking the business service's GetWeatherForecast() method to return result as below
var expResult = new WeatherForecast[]
{
new WeatherForecast(DateTime.Now, 26, "Bengaluru")
};

//mocking the business service's GetWeatherForecast()
_mockServices.WeatherForecastServiceMock.Setup(m => m.GetWeatherForecast()).ReturnsAsync(expResult);
//calling the api
var response = await _client.GetAsync("/weatherforecast");
string jsonString = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<WeatherForecast[]>(jsonString);
//testing the response
Assert.Equal(response.StatusCode, System.Net.HttpStatusCode.OK);
Assert.Equal(expResult, result);
}
}
}

Saturday, 25 June 2022

props vs emit in vue.js

 In my last article here , I tried to explain about data(), props, methods and components. Here I’m gonna explain about emit function of vue.js.

<template>
<div>
<input type="text" v-model="firstName"/>
<input type="text" v-model="lastName"/>
<br/>
<button @click='onButtonClick()'>
Click Me
</button>
</div>
</template>
<script>
export default {

props: ['firstName', 'lastName'],

emits: ['onClick'],

methods :{
onButtonClick($event){
this.$emit("onClick", { fName: this.firstName, lName:this.lastName});
}
},

}
</script>
<script>
import MyComp from './MyComponent.vue' //import the component
export default {

components: {
'my-comp' : MyCompl //define the component
},

data() {
return {
firstName: 'Binod',
lastName: 'Mahto',
fullName:'',
}
},

methods : {
mtdCalculateFullName(payload) {
this.$data.firstName = payload.fName;
this.$data.lastName = payload.lName;
this.$data.fullName = this.$data.firstName + ' ' + this.$data.lastName;
}
},
}
</script>
<template>
<div>
<my-comp :first-Name='firstName' :last-Name='lastName' @on-Click='mtdCalculateFullName'></my-comp>
</div>
<div>
<p>Full Name:</p><p>{{fullName}}</p>
</div>
</template>

Thursday, 23 June 2022

data vs props and methods vs computed in Vue.js

 Vue.js is a versatile & popular framework for building web user interfaces. Even I feel, compare to other UI frameworks, Vue framework seems to be easier to learn & code. There are four basic & major concepts of Vue framework which often seems to be confusing from each others, specially for beginners.

<script>
export default {
data() {
return {
firstName: 'Binod',
lastName: 'Mahto',
fullName:'',
methodcount:0,
computedcount:0
}
},

methods : {
mtdCalculateFullName() {
this.$data.methodcount++;
this.$data.fullName = this.$data.firstName + ' ' + this.$data.lastName;
}
},

computed : {
cmptCalculateFullName() {
this.$data.computedcount++;
this.$data.fullName = this.$data.firstName + ' ' + this.$data.lastName;
}
}

}
</script>
<template>
<input type="text" v-model="firstName">
<input type="text" v-model="lastName">
<div>
<button @click='mtdCalculateFullName()'>
Click Me
</button>
<p>Full Name:</p><p>{{fullName}}</p>
<p>count: {{methodcount}}</p>
</div>
<div>
<button @click='cmptCalculateFullName'>
Click Me
</button>
<p>Full Name:</p><p>{{fullName}}</p>
<p>count: {{computedcount}}</p>
</div>
</template>

data():

data() {
return {
firstName: 'Binod',
lastName: 'Mahto',
fullName:'',
methodcount:0,
computedcount:0
}
}
this.$data.{datamembername} 
//not necessary to use $data instead you do this.{datamembername} but i'm doing this for readability purpose.
<template>
<div>
<p>{{greetingMessage}}</p>
</div>
</template>
<script>
export default {
props: ['greetingMessage']
}
</script>
<script>

import MyComp from './MyComp.vue' //import it first
export default {
components: {
MyComp
//define the component
}
,
data() {
return {
message: 'Hi This is a message for props',
}
},


}
</script>
<template>
<MyComp greetingMessage ='Hi This is props'></MyComp>
<MyComp greeting-Message ='Hi This is props'></MyComp>
<MyComp :greeting-Message ='message'></MyComp>

</div>
</template>
<template>
<div>
<p>{{greetingMessage}}</p>
</div>
</template>
<script>
export default {
props: {
greetingMessage : string,
}

}
</script>
methods:{
mymethod1(payload: any){
//logic goes here
}

//syntax to define async methods
async mymethod2(payload: any){
//logic goes here
}
}
<button @click='mtdCalculateFullName()'>
export default {
data() {
return {
firstName: 'Binod',
lastName: 'Mahto'
}
},
computed: {
computedFullName: {
// getter
get() {
return this.$data.firstName + ' ' + this.$data.lastName
},

// setter
set(newValue) {
// Note: we are using destructuring assignment syntax here.
[this.$data.firstName, this.$data.lastName] = newValue.split(' ')

}
}
}
}
this.computedFullName = 'James Bond';//to set the new value
this.computedFullName; // to get the value.
//this is not allowed
computed:{
cmptCalculateFullName(payload : string)
{
}
}
computed: {
computedFullName: {
// setter
set(newValue) {
// Note: we are using destructuring assignment syntax here.
[this.$data.firstName, this.$data.lastName] = newValue.split(' ')
}
}
}