UnitTest add item to list and check if exists - c#

I want to test if my code works properly so I am writing some unit tests for it.
I want to check when and item in my list with the same values is added again it should return false.
I do not really understand how to set this up. I hope some can help me out.
Below my code
GuestResponseRepository
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using PartyInvites.Abstract;
namespace PartyInvites.Models
{
public class GuestResponseRepository : IRepository
{
private static List<GuestResponse> responses = new List<GuestResponse>();
IEnumerable<GuestResponse> IRepository.GetAllResponses()
{
return responses;
}
bool IRepository.AddResponse(GuestResponse response)
{
if (responses.Any(x => x.Email == response.Email)) //here
{
if (responses.Any(x => x.WillAttend == response.WillAttend)) //here
{
return false;
}
var attend = responses.First(x => x.Email == response.Email && x.WillAttend != response.WillAttend);
attend.WillAttend = response.WillAttend;
return true;
}
responses.Add(response);
return true;
}
}
}
My interface which communicates with the GuestResponseRepository
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PartyInvites.Models;
namespace PartyInvites.Abstract
{
public interface IRepository
{
IEnumerable<GuestResponse> GetAllResponses();
bool AddResponse(GuestResponse response);
}
}
A piece of my Homecontroller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PartyInvites.Models;
using PartyInvites.Abstract;
namespace PartyInvites.Controllers {
public class HomeController : Controller {
private IRepository repository;
public HomeController(IRepository iRepository)
{
this.repository = iRepository;
}
[HttpGet]
public ViewResult RsvpForm() {
return View();
}
[HttpPost]
public ViewResult RsvpForm(GuestResponse guestResponse) {
if (ModelState.IsValid) {
bool result = repository.AddResponse(guestResponse);
ViewBag.Response = result;
repository.AddResponse(guestResponse);
return View("Thanks", guestResponse);
}
else
{
// there is a validation error
return View();
}
}
}
}
My UnitTest what I got so far
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PartyInvites.Abstract;
using PartyInvites.Controllers;
using PartyInvites.Models;
using Moq;
namespace Aanmelden
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void FirstResponse()
{
//Arange
Mock<IRepository> mock = new Mock<IRepository>();
mock.Setup(m => m.AddResponse()).Returns(new GuestResponse[] {
new GuestResponse {Name = "Valheru", Email = "valheru#hotmail.com", Phone = "12345678", WillAttend = true}
});
HomeController controller = new HomeController(mock.Object);
//Act
new GuestResponse
{
Name = "Valheru",
Email = "valheru#hotmail.com",
Phone = "12345678",
WillAttend = true
};
//Assert
if viewbag.response = result == false test succeeded
}
}
}
for some reason mock.Setup(m => m.**AddResponse**()).Returns(new GuestResponse[] {...
"AddResponse" aint right says Visual Studio ->
there is no argument given that corresponds to the required formal
parameter 'response' of IRepository.AddResponse(GuestReponse)
I am also no sure about my Act piece of code and I lost it totally with the Assert part. I hope someone can help me out!

you should It.IsAny<GuestResponse>() as a paramater in order to match the signature of your interface
Mock<IRepository> mock = new Mock<IRepository>();
mock.Setup(m => m.AddResponse(It.IsAny<GuestResponse>())).Returns(true);

Based on
I want to check when an item in my list with the same values is added
again it should return false.
You should actually be testing the GuestResponseRepository implementation itself and not the controller.
[TestMethod]
public void Duplicate_Added_Should_Return_False {
//Arrange
var sut = new GuestResponseRepository();
var model = new GuestResponse
{
Name = "Valheru",
Email = "valheru#hotmail.com",
Phone = "12345678",
WillAttend = true
};
sut.AddResponse(model);
var expected = false;
//Act
var actual = sut.AddResponse(model);
//Assert
Assert.AreEqual(expected, actual);
}

Related

Unit testing - mocking service which has a List as a data storage

I'm new to Unit testing and I'm trying to learn how to do it.
I'm using Moq to Mock the dependencies.
Here's my Testing class:
using Microsoft.AspNetCore.Mvc;
using Moq;
using scholarship.Controllers;
using scholarship.Services.Interface;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Xunit;
namespace Testing
{
public class InternControllerTests
{
private Mock<IInternService> _internService = new Mock<IInternService>();
[Theory]
[InlineData("00000000-0000-0000-0000-000000000001")]
[InlineData("00000000-0000-0000-0000-000000000002")]
public void Delete_Intern(Guid id)
{
InternsController internsController
= new InternsController(_internService.Object);
var actual = internsController.DeleteIntern(id) as ObjectResult;
Assert.True(actual is OkObjectResult);
}
[Theory]
[InlineData("00000000-0000-0000-0000-000000000000")]
[InlineData("00000000-0000-0000-0000-000000000005")]
public void Delete_Intern_NotFound(Guid id)
{
InternsController internsController
= new InternsController(_internService.Object);
var actual = internsController.DeleteIntern(id) as ObjectResult;
Assert.True(actual is NotFoundObjectResult);
}
}
}
the service:
using scholarship.Models;
using scholarship.Services.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace scholarship.Services.Class
{
public class InternCollectionService : IInternService
{
public static List<Intern> _interns = new List<Intern>
{
new Intern { ID = new Guid("00000000-0000-0000-0000-000000000001"), FirstName = "Octavian", LastName = "Niculescu", DateOfBirth=new DateTime(2001,01,01)},
new Intern { ID = new Guid("00000000-0000-0000-0000-000000000002"), FirstName = "Andrei", LastName = "Popescu", DateOfBirth=new DateTime(2002,01,01)},
new Intern { ID = new Guid("00000000-0000-0000-0000-000000000003"), FirstName = "Calin", LastName = "David", DateOfBirth=new DateTime(2003,01,01)},
};
public bool Create(Intern model)
{
_interns.Add(model);
return true;
}
public bool Delete(Guid id)
{
int index = _interns.FindIndex(intern => intern.ID == id);
if (index == -1)
{
return false;
}
_interns.RemoveAt(index);
return true;
}
public Intern Get(Guid id)
{
return (from intern in _interns
where intern.ID == id
select intern).FirstOrDefault();
}
public List<Intern> GetAll()
{
return _interns;
}
public bool Update(Guid id, Intern model)
{
int index = _interns.FindIndex(intern => intern.ID == id);
if (index == -1)
{
return false;
}
model.ID = id;
_interns[index] = model;
return true;
}
}
}
the controller
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using scholarship.Models;
using scholarship.Services.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace scholarship.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class InternsController : ControllerBase
{
IInternService _internService;
public InternsController(IInternService internService)
{
_internService = internService ?? throw new ArgumentNullException(nameof(internService));
}
[HttpGet]
public IActionResult GetInterns()
{
return Ok(_internService.GetAll());
}
[HttpGet("{Id}", Name = "GetIntern")]
public IActionResult GetIntern([FromRoute] Guid Id)
{
Intern? intern = _internService.Get(Id);
if(intern == null)
{
return NotFound();
}
return Ok(intern);
}
[HttpPost]
public IActionResult AddIntern([FromBody] Intern intern)
{
intern.ID = Guid.NewGuid();
_internService.Create(intern);
return CreatedAtRoute("GetIntern", new { ID = intern.ID }, intern);
}
[HttpPut("{id}")]
public IActionResult UpdateIntern([FromBody] Intern intern, Guid id)
{
if (intern == null)
{
return BadRequest("Intern cannot be null");
}
_internService.Update(id, intern);
return Ok();
}
[HttpDelete("{id}")]
public IActionResult DeleteIntern(Guid id)
{
bool deleted = _internService.Delete(id);
if (deleted == false)
{
return NotFound("Intern cannot be found");
}
return Ok();
}
}
}
The project is a very small one, I used it to start learning .net.
Now I want to learn Unit Testing, and I'm trying to learn Unit Testing.
The Delete tests fail.
I think this happens because by mocking the service, there is no list with data like in the service.
So, how should I make the Delete tests work? Should I somehow mock that list too? (I don't know how)
Thanks.
Although it is not best practice to test everything in one shoot, you can change your code as per below and test by status code with your inline data and hardcoded return type:
[Theory]
[InlineData("00000000-0000-0000-0000-000000000001", true, 200)]
[InlineData("00000000-0000-0000-0000-000000000002", true, 200)]
[InlineData("00000000-0000-0000-0000-000000000000", false, 404)]
[InlineData("00000000-0000-0000-0000-000000000005", false, 404)]
public void Delete_Intern(Guid id, bool expectedReturn, int expectedStatusCode)
{
InternsController internsController
= new InternsController(_internService.Object);
_internService.Setup(x => x.Delete(It.Is<Guid>(x => x.Equals(id)))).Returns(expectedReturn);
var actual = internsController.DeleteIntern(id) as ObjectResult;
Assert.True(actual.StatusCode == expectedStatusCode);
}
However, you can read the How to use Moq and xUnit for Unit Testing Controllers in ASP.NET Core which I think is a good practice.

Using connection string in ASP.Net MVC controller to retrieve records

I am trying to retrieve records in my index ActionResult but keep getting a "The name 'connectionString' does not exist in the current context" error. Please see below code:
using Microsoft.Xrm.Tooling.Connector;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TestMVCApp.DAL;
using TestMVCApp.Models;
namespace TestMVCApp.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
var objDAL = new DAL_InvoicesEntity();
List<InvoicesModel> invInfo = objDAL.RetriveRecords(connectionString);
ViewBag.invInfo = invInfo;
return View();
}
}
}
DAL class file:
using System;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using TestMVCApp.Models;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Tooling.Connector;
using System.Linq;
namespace TestMVCApp.DAL
{
public class DAL_InvoicesEntity
{
public List<InvoicesModel> RetriveRecords(string connectionString)
{
var svc = new CrmServiceClient(connectionString);
var query = new QueryExpression()
{
EntityName = "new_invoices",
ColumnSet = new ColumnSet("new_invoicesid", "ttt_customer", "ttt_invoiceid", "ttt_paymentreceived", "ttt_commission", "ttt_adminfee", "ttt_discountamount"),
TopCount = 10
};
var invoices = svc.RetrieveMultiple(query).Entities.ToList();
var invoiceModels = invoices.Select(i =>
new InvoicesModel
{
InvoiceID = i.GetAttributeValue<Guid>("new_invoicesid"),
ClientName = i.GetAttributeValue<EntityReference>("ttt_customer"),
InvoiceNumber = i.GetAttributeValue<string>("ttt_invoiceid"),
AdminFee = i.GetAttributeValue<decimal>("ttt_adminfee"),
Discount = i.GetAttributeValue<decimal>("ttt_discountamount"),
PaymentReceived = i.GetAttributeValue<decimal>("ttt_paymentreceived")
})
.ToList();
return invoiceModels;
}
}
}
Please assist if you can
You should define connectionString variable before using it.
public class HomeController : Controller
{
private const connectionString = "YourConnectionString";
public ActionResult Index()
{
var objDAL = new DAL_InvoicesEntity();
List<InvoicesModel> invInfo = objDAL.RetriveRecords(connectionString);
ViewBag.invInfo = invInfo;
return View();
}
}

Unable to resolve service for type while attempting to activate a service in startup.cs

Have spent way too much time trying to figure this out. Thanks for any help. .Net Core 3.1 trying to register a service in Startup.cs
Error CS0311: The type 'Apex.UI.MVC.ProjectService' cannot be used as type parameter 'TImplementation' in the generic type or method ServiceCollectionServiceExtensions.AddScoped<TService, TImplementation>(IServiceCollection). There is no implicit reference conversion from 'Apex.UI.MVC.ProjectService' to 'Apex.EF.Data.IProjects'. (CS0311) (Apex.UI.MVC)
services.AddScoped<IProjects, ProjectService>();
using System;
using Apex.EF.Data;
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;
using System.Linq;
using Apex.UI.MVC.Models.Projects;
namespace Apex.UI.MVC.Controllers
{
public class ProjectController : Controller
{
private IProjects _projects;
public ProjectController(IProjects projects)
{
_projects = projects;
}
public IActionResult Index()
{
var projectModels = _projects.GetAll();
var listingResult = projectModels
.Select(result => new ProjectIndexListingModel
{
Id = result.Id,
ProjectName = result.ProjectName,
ProjectImage = result.ProjectImage
});
var model = new ProjectIndexModel()
{
Project = listingResult
};
return View(model);
}
}
}
using System;
using System.Collections.Generic;
using Apex.EF.Data;
using Apex.EF.Data.Models;
namespace Apex.EF.Data
{
public interface IProjects
{
IEnumerable<Project> GetAll();
Project GetById(int id);
void Add(Project newProject);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Apex.EF.Data;
using Apex.EF.Data.Models;
using Microsoft.EntityFrameworkCore;
namespace ApexServices
{
public class ProjectService : IProjects
{
private ApexContext _context;
public ProjectService(ApexContext context)
{
_context = context;
}
public void Add(Project newProject)
{
_context.Add(newProject);
_context.SaveChanges();
}
public IEnumerable<Project> GetAll()
{
return _context.Projects
.Include(project => project.Status.IsInShop == true);
}
public Project GetById(int id)
{
return _context.Projects
.Include(project => project.Status.IsInShop==true)
.FirstOrDefault(project => project.Id == id);
}
}
}
The namespaces shown in the exception are different to the example code shown. There are probably conflicting types in the project (not shown).
If that is really the case, then include the full namespace when registering the type with the container to avoid conflicts.
Based on the shown code, that would be
services.AddScoped<IProjects, ApexServices.ProjectService>();

How to mock a method that returns a list of interfaces

This is my repository method:
public async Task<IList<IVehicleMake>> GetAllMakes()
{
var makes = Context.VehicleMakes.AsQueryable();
return new List<IVehicleMake>(AutoMapper.Mapper.Map<List<VehicleMake>>(await makes.ToListAsync()));
}
I know how to mock the method that returns a concrete type, but as you can see, this method returns a list of Interfaces "IVehicleMake".
Is it possible to mock this kind of method and how?
You can simply use a mocking framework such as Moq. It is not so different than mocking a simple interface.
Here is a sample code using MS Test and Moq
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace UnitTestProject1
{
public class Vehicle{}
public interface IVehicleMake
{
Vehicle Make();
}
public interface IVehicleMakeRepository
{
Task<IList<IVehicleMake>> GetAllMakes();
}
public class MyService
{
private readonly IVehicleMakeRepository vehicleMakeRepository;
public MyService(IVehicleMakeRepository vehicleMakeRepository)
{
this.vehicleMakeRepository = vehicleMakeRepository;
}
public async Task DoSomething()
{
var makes = await vehicleMakeRepository.GetAllMakes();
foreach (var make in makes)
{
var vehicule = make.Make();
}
}
}
public class MyServiceTest
{
[TestClass]
public class DoSomething
{
[TestMethod]
public async Task Should_CallAllMakersOnce()
{
//Arrange
var mockedMakers = new[] { new Mock<IVehicleMake>(), new Mock<IVehicleMake>(), };
foreach (var mockedMaker in mockedMakers)
{
mockedMaker.Setup(m => m.Make()).Returns(new Vehicle()).Verifiable();
}
var mockedRepository = new Mock<IVehicleMakeRepository>();
mockedRepository
.Setup(m => m.GetAllMakes())
.ReturnsAsync(mockedMakers.Select(mm => mm.Object).ToList())
.Verifiable();
var service = new MyService(mockedRepository.Object);
//Act
await service.DoSomething();
//Assert
mockedRepository.Verify(m => m.GetAllMakes(), Times.Once);
foreach (var mockedMaker in mockedMakers)
{
mockedMaker.Verify(m => m.Make(), Times.Once);
}
}
}
}
}

Can the MVC Controller method be mocked using the NSubstitute

I need to test and mock a method found inside a controller. Is is possible to mock a method inside the controller, without implementing an interface using NSubstitute framework.
Here is my Controller page code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Syncfusion.Cluster.Manager
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
int result = Sum(7, 7);
return View();
}
public virtual int Sum(int a, int b)
{
return 0;
}
}
}
Here is my Test code and the Sum always found to be '0' inside the controller while I debugged it. The Sum function inside the controller is not get overrides.
using System;
using NUnit.Framework;
using Manager;
using Base.Classes.Models.SecurityBase;
using NSubstitute;
using BaseProject;
using System.Web.Mvc;
using System.Web.Http;
namespace NSubstituteControllerSupport
{
[TestFixture]
public class UnitTest1
{
[Test]
public void TestMethod1()
{
var controller = new HomeController();
//var actionMethod = Substitute.For<HomeController>();
//actionMethod.Sum(Arg.Any<int>(), Arg.Any<int>()).Returns(14);
//var actual = controller.Index();
var validation = Substitute.ForPartsOf<HomeController>();
validation.When(x => x.Sum(a: Arg.Is(7), b: Arg.Is(7))).DoNotCallBase();
validation.Sum(7, 7).Returns(14);
var actuals = controller.Index();
}
}
}
Here is my testing code for the Class Library project I successfully mocked a method without implementing an interface.
[Test]
public void TestMethod2()
{
#region variableDecleration
var adHost = new ActiveDirectoryHost();
adHost.AdPath = #"C:\User\Security\1.0.0.0";
adHost.CnNames = "CN=USERS";
adHost.DomainName = "USER.COM";
adHost.DomainPath = "DC=USER,DC=COM";
adHost.Fqn = "HOSTNAME.USER.COM.USER.COM";
adHost.HostName = "hostname.user.com";
adHost.OuPath = "OU=NewSecur";
adHost.SuperGroupName = "usergroup_1";
adHost.IpAddress = "xxx.xx.xx.x";
var adUserName = "username";
var adPassword = "password";
#endregion variableDecleration
var validation = Substitute.ForPartsOf<ValidationHandler>();
validation.GetUserGroupList(userName: Arg.Is(adUserName ), recursive: Arg.Is(false), adHost: Arg.Is(adHost), adUsername: Arg.Is(adUserName), adPassword: Arg.Is(adPassword)).Returns("usergroup_1,usergroup_2");
var isUserInGroup = validation.IsUserMemberOfGroup(adUsername, "usergroup_1", adHost, adUserName, adPassword);
Assert.That(isUserInGroup, Is.EqualTo(true));
}
The following should do the job:
// arrange
var controller = Substitute.For<HomeController>();
controller.Sum(7, 7).Returns(14);
// act
var actual = controller.Index();
// assert
...

Categories