Xunit and Mock data with Moq - c#

I'm new to unit testing, can anyone advise how to test public method (CreateUser) below using xUnit and Moq, thanks!
public async Task<bool> CreateUser(UserDTO newUser)
{
newUser.CustomerId = _userResolverService.GetCustomerId();
if (await CheckUserExists(newUser)) return false;
var salt = GenerateSalt(10);
var passwordHash = GenerateHash(newUser.Password, salt);
await _usersRepository.AddAsync(new User()
{
Role = newUser.Role,
CretedOn = DateTime.Now,
CustomerId = newUser.CustomerId,
Email = newUser.Email,
FirstName = newUser.FirstName,
LastName = newUser.LastName,
PasswordHash = passwordHash,
Salt = salt,
UpdatedOn = DateTime.Now
});
return true;
}
Private methods below
Check if user exists simply returns number of existing users
private async Task<bool> CheckUserExists(UserDTO user)
{
var users = await _usersRepository.GetAllAsync();
var userCount = users.Count(u => u.Email == user.Email);
return userCount > 0;
}
Hash Generation
private static string GenerateHash(string input, string salt)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(input + salt);
var sha256 = SHA256.Create();
var hash = sha256.ComputeHash(bytes);
return ByteArrayToString(hash);
}
Salt Generaion
private static string GenerateSalt(int size)
{
var rng = RandomNumberGenerator.Create();
var buff = new byte[size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
private static string ByteArrayToString(byte[] ba)
{
var hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
Thanks,
J
EDIT 1
This is what I have so far:
[Fact]
public async void CreateUser_True()
{
//arrange
var dataSource = new Mock<IRepository<User, int>>();
var userResolverService = new Mock<IUserResolverService>();
var tokenService = new Mock<ITokenService>();
var users = new List<User>();
users.Add(new User()
{
Email = "test#test.com",
CustomerId = 1
});
dataSource.Setup(m => m.GetAllAsync()).ReturnsAsync(users); // Error Here with converting async task to IEnumerable...
var accountService = new AccountService(dataSource.Object,userResolverService.Object,tokenService.Object);
//act
//assert
}
Main problem is that I have no idea how to Mock, set up behavior of private Method "CheckUserExists", as it's calling IRepository which is mocked for class, so will this in this case return my mock setup for GetAllAsync from this private method?
EDIT 2
public async Task<TEntity> AddAsync(TEntity entity)
{
if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
_entities.Add(entity);
await _context.SaveChangesAsync();
return entity;
}
EDIT 3
[Fact]
public async void CreateUser_True()
{
//arrange
var users = new List<User>();
users.Add(new User()
{
Email = "test#test.com",
CustomerId = 1
});
_dataSource.Setup(m => m.GetAllAsync()).ReturnsAsync(users);
_dataSource.Setup(m => m.AddAsync(It.IsAny<User>())).Returns<User>(Task.FromResult);
var accountService = new AccountService(_dataSource.Object, _userResolverService.Object, _tokenService.Object);
//act
var result = await accountService.CreateUser(new UserDTO()
{
Email = "truetest#test.com"
});
var updatedUsersList = await _dataSource.Object.GetAllAsync();
var usersCount = updatedUsersList.Count();
//assert
Assert.True(result);
Assert.Equal(2, usersCount);
}

As the method being tested is async you need to setup all async dependencies to allow the method flow to completion. As for the private method, you want to setup the behavior of any dependencies that are used within that method, which in this case is the users repository.
[Fact]
public async Task CreateUser_True() {
//arrange
var usersRepository = new Mock<IRepository<User, int>>();
var userResolverService = new Mock<IUserResolverService>();
var tokenService = new Mock<ITokenService>();
var user = new User() {
Email = "test#test.com",
CustomerId = 1
};
var users = new List<User>() { user };
usersRepository.Setup(_ => _.GetAllAsync()).ReturnsAsync(users);
usersRepository.Setup(_ => _.AddAsync(It.IsAny<User>()))
.Returns<User>(arg => Task.FromResult(arg)) //<-- returning the input value from task.
.Callback<User>(arg => users.Add(arg)); //<-- use call back to perform function
userResolverService.Setup(_ => _.GetCustomerId()).Returns(2);
var accountService = new AccountService(usersRepository.Object, userResolverService.Object, tokenService.Object);
//act
var actual = await accountService.CreateUser(new UserDto {
Email = "email#example.com",
Password = "monkey123",
//...other code removed for brevity
});
//assert
Assert.IsTrue(actual);
Assert.IsTrue(users.Count == 2);
Assert.IsTrue(users.Any(u => u.CustomerId == 2);
}
Read up on Moq Quickstart to get a better understanding of how to use the mocking framework.

#sziszu As I understand correctly you can setup mock for unit test of your your public method. here is solution.
I have rewrite your code and my project structure is something look like visual studio project structure
Here is my code snippets
UserOperation Class
public class UserOperation
{
#region Fields
private readonly IUserResolverService _userResolverService;
private readonly IUsersRepository _usersRepository;
#endregion
#region Constructor
public UserOperation(IUserResolverService userResolverService, IUsersRepository usersRepository)
{
_userResolverService = userResolverService;
_usersRepository = usersRepository;
}
#endregion
#region Public Methods
public async Task<bool> CreateUser(UserDTO newUser)
{
newUser.CustomerId = _userResolverService.GetCustomerId();
if (await CheckUserExists(newUser)) return false;
var salt = GenerateSalt(10);
var passwordHash = GenerateHash(newUser.Password, salt);
await _usersRepository.AddAsync(new User
{
Role = newUser.Role,
CretedOn = DateTime.Now,
CustomerId = newUser.CustomerId,
Email = newUser.Email,
FirstName = newUser.FirstName,
LastName = newUser.LastName,
PasswordHash = passwordHash,
Salt = salt,
UpdatedOn = DateTime.Now
});
return true;
}
#endregion
#region PrivateMethods
private async Task<bool> CheckUserExists(UserDTO user)
{
var users = await _usersRepository.GetAllAsync();
var userCount = users.Count(u => u.Email == user.Email);
return userCount > 0;
}
private static string GenerateHash(string input, string salt)
{
var bytes = Encoding.UTF8.GetBytes(input + salt);
var sha256 = SHA256.Create();
var hash = sha256.ComputeHash(bytes);
return ByteArrayToString(hash);
}
private static string GenerateSalt(int size)
{
var rng = RandomNumberGenerator.Create();
var buff = new byte[size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
private static string ByteArrayToString(byte[] ba)
{
var hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
#endregion
}
Below are my repositories and services.
public interface IUsersRepository
{
Task AddAsync(User user);
Task<ICollection<User>> GetAllAsync();
}
public class UsersRepository : IUsersRepository
{
public Task AddAsync(User user)
{
//Code for adding user
}
public Task<ICollection<User>> GetAllAsync()
{
//Code for get all user from DB
}
}
public interface IUserResolverService
{
string GetCustomerId();
}
public class UserResolverService : IUserResolverService
{
public string GetCustomerId()
{
//Code for Getting customerID.
}
}
Here You can test using mock
public class UserOperationTest
{
private readonly UserOperation _sut;
private readonly IUserResolverService _userResolverService;
private readonly IUsersRepository _userRepository;
public UserOperationTest()
{
_userResolverService = Substitute.For<IUserResolverService>();
_userRepository = Substitute.For<IUsersRepository>();
_sut = new UserOperation(_userResolverService, _userRepository);
}
[Fact]
public void CreateUser_SuccessWithMock()
{
// Arrange
var userDto = new UserDTO
{
Email = "ThirdUserUserEmail.Com"
};
var userList = new List<User>()
{
new User{CustomerId = "1", Email = "FirstUserEmail.Com"},
new User{CustomerId = "2", Email = "SecondUserEmail.Com"}
};
_userResolverService.GetCustomerId().Returns("3");
_userRepository.GetAllAsync().Returns(userList);
_userRepository.When(x => x.AddAsync(Arg.Any<User>())).Do(x =>
{
userList.Add(new User {Email = userDto.Email, CustomerId = userDto.CustomerId});
});
//Act
var result = _sut.CreateUser(userDto);
// Assert
result.Result.Should().BeTrue();
_userResolverService.Received(1).GetCustomerId();
_userRepository.Received(1).GetAllAsync();
_userRepository.Received(1).AddAsync(Arg.Any<User>());
userList.Count.Should().Be(3);
}
}

Related

How to set multiple objects to Mocking DbSet<T>

I have my interface as below
public interface IAssessmentDbContext
{
DatabaseFacade Database { get; }
DbSet<Domain.Entities.Assessment> Assessments { get; }
DbSet<AssessmentType> AssessmentTypes { get; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
DbSet<AssessmentType> GetAssessmentTypes();
}
and i'm trying to mock data as follows.
public class AssessmentsControllerTests
{
private readonly IFixture _fixture;
private readonly Mock<IAssessmentDbContext> dbContextMock;
private readonly Mock<IRequestClient<GetCandidates>> requestClientMock;
private readonly AssessmentsController controller;
//private readonly Mock<CancellationToken> cancellationTokenMock;
public AssessmentsControllerTests()
{
dbContextMock = _fixture.Freeze<Mock<IAssessmentDbContext>>();
var data1 = new List<Domain.Entities.AssessmentType>();
var data = new Domain.Entities.AssessmentType()
{
Id = new Guid("CD4FA15F-B882-4995-57A3-08DA9A133B59"),
AssessmentTypeName = "Big50",
AssessmentTypeText = "Big Fifty"
};
data1.Add(data);
DbSet<Domain.Entities.AssessmentType> myDbSet = GetQueryableMockDbSet(data1);
var dataAssessment = new List<Domain.Entities.Assessment>();
Domain.Entities.Assessment obj = new Domain.Entities.Assessment()
{
AssessmentTypeId = new Guid("CD4FA15F-B882-4995-57A3-08DA9A133B59"),
UserId = new Guid("1572EA1B-4CBD-4C05-D03C-08DA47BC4FD9"),
CreatedAt = DateTime.Now,
Id = Guid.NewGuid()
};
dataAssessment.Add(obj);
DbSet<Domain.Entities.Assessment> myDbSetAssessment = GetQueryableMockDbSet(dataAssessment);
dbContextMock.Setup(x=>x.GetAssessmentTypes()).Returns(myDbSet);
dbContextMock.Setup(x => x.Assessments).Returns(myDbSetAssessment);
controller = new AssessmentsController(dbContextMock.Object);
}
[Fact]
public void GetAssessments_ShouldReturnData_WhenWithUserId()
{
// Arrange
var userIdMock = _fixture.Create<Guid>();
CancellationToken token = _fixture.Create<CancellationToken>();
// Act
var result = controller.GetAssessments("1572EA1B-4CBD-4C05-D03C-08DA47BC4FD9", token);
// Assert
result.Should().NotBeNull();
result.Should().BeAssignableTo<IActionResult>();
}
private static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
{
var queryable = sourceList.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s));
return dbSet.Object;
}
}
}
How can I mockup both Assessments and AssessmentType in IAssessmentDbContext

How to mock AbstractValidator

I am failing on the BeUniqueEmail with the error message (below). How can I mock this correctly? I have included the validator and the test below.
The tests passed when I removed the BeUnique email validation
Message:
System.NotImplementedException : The method or operation is not implemented.
public class CreateStudentCommandValidator : AbstractValidator<CreateStudentCommand>
{
private readonly IApplicationDbContext _context;
public CreateStudentCommandValidator(IApplicationDbContext context)
{
_context = context;
RuleFor(v => v.Email)
.NotEmpty().WithMessage("Email is required.")
.MaximumLength(30).WithMessage("Email must not exceed 30 characters.")
.MustAsync(BeUniqueEmail).WithMessage("The specified email already exists.");
}
public async Task<bool> BeUniqueEmail(CreateStudentCommand model, string email, CancellationToken cancellationToken)
{
bool emailExists = await _context.Students
.Where(x => x.Email == email)
.Where(x => !x.IsDeleted)
.CountAsync() > 0;
return !emailExists;
}
}
Testing
[Test]
public async Task CreateStudentCommand_Success()
{
var mockSet = new Mock<DbSet<Student>>();
var context = new Mock<IApplicationDbContext>();
context.Setup(m => m.Student).Returns(mockSet.Object);
var handler = new CreateStudentCommandHandler(context.Object);
var validator = new CreateStudentCommandValidator(context.Object);
//var mockedValidator = new Mock<IValidator<CreateStudentCommandValidator>>();
//var mock1 = new Mock<AbstractValidator<CreateStudentCommandValidator>>();
var command = new CreateStudentCommand
{
StudentType = "Test1",
Email = "Test1#email.com",
FirstName = "Test1",
LastName = "Test1",
IsActive = true
};
var result = await handler.Handle(command, new CancellationToken());
// Act
var validationResult = await validator.ValidateAsync(command);
// Assert
Assert.True(validationResult.IsValid);
Assert.IsInstanceOf<Guid>(result);
}
Using Moq, a solution to this could be as follows.
[Test]
public async Task TestValidation()
{
var context = Mock.Of<ApplicationDbContext>();
var validator = new CreateStudentCommandValidator(context);
var command = new CreateStudentCommand
{
StudentType = "Test1",
Email = "Test1#email.com",
FirstName = "Test1",
LastName = "Test1",
IsActive = true
};
var validationResult = await validator.ValidateAsync(command);
Assert.True(validationResult.IsValid);
}
Not knowing your Context, I implemented a simple dummy.
public interface IApplicationDbContext
{
List<Student> Students { get; set; }
}
public class ApplicationDbContext : IApplicationDbContext
{
public ApplicationDbContext()
{
Students = new List<Student>();
}
public List<Student> Students { get; set; }
}
This all depends on the use of Moq however, If you are using some other Mocking Service the Implementation will change.
*My Previous answer was intended to explain the implementation of Mocking Method Results. But in this case you do not need to mock the CreateStudentCommandValidator

Unit test for update method in C# using Mock

I am trying to write a unit test for My Processor class I have two problems
I do not know how to test my Methods Only.
this is my processor
OrderProcessor class
public class OrderProcessor
{
public void Process(CustomersOrder order)
{
var oldOrder = _repository.GetOldorderId(order.Code.Value);
if (oldOrder != 0)
{
updateOrder(order);
}
else
{
SaveOrder(order);
}
}
private void updateOrder(CustomersOrder order)
{
_repository.UpdateOrder(order);
}
private void SaveOrder(CustomersOrder order)
{
_repository.SaveOrder(order);
}
}
}
Repository class
public class Repository : IRepository
{
private static PracticeEntities4 _context;
public Repository(PracticeEntities4 context)
{
_context = context;
}
public int GetOldCustomerId( int customerCode)
{
var CuID= _context.Customers.First(e => e.Code == customerCode);
return CuID.Id;
}
public int GetOldorderId(int orderCode)
{
var oldOrder = _context.CustomersOrders.FirstOrDefault(e => e.Code == orderCode);
return oldOrder.Id;
}
public void SaveCustomer(Customer customer)
{
_context.Customers.Add(customer);
_context.SaveChanges();
}
public void SaveOrder(CustomersOrder order)
{
_context.CustomersOrders.Add(order);
_context.SaveChanges();
}
public void UpdateOrder(CustomersOrder order)
{
_context.CustomersOrders.AddOrUpdate(order);
_context.SaveChanges();
}
}
and this is My unit test I don't know how to fix it and where is the problem exactly and also I want to test the Methods too.
UnitTests Class
[TestClass]
public class OrderProcessorTest
{
[ClassInitialize]
{...}
[TestInitialize]
public void TestInitialize()
{
....
}
[TestMethod]
public void Customer_OrderProcess()
{
//Arange
Mock<IRepository> mock= new Mock<IRepository>();
//Act
mock.Setup(e => e.GetOldCustomerId(1001)).Returns(3);
mock.Setup(e => e.GetOldStoreId(200)).Returns(3);
var dtos = OrderDeserializer.Deserialize(path);
var dto = dtos.First(e => e.Code == 300);
OrderBuilder builder = new OrderBuilder(mock.Object);
builder.OrderBuild(dto);
//Asset
Assert.AreEqual(0, _orders.Count);
}
}
Order Builder Class
public class OrderBuilder
{
public IRepository _repository { get; set; }
public OrderBuilder(IRepository repository)
{
_repository = repository;
}
public CustomersOrder OrderBuild(OrderDto dto)
{
var oldStoreId = _repository.GetOldStoreId(dto.StoreCode);
var oldCustomerId = _repository.GetOldCustomerId(dto.CustomerCode);
return new CustomersOrder()
{
OrderDate = Convert.ToDateTime(dto.OrderDate),
OrderStatus = dto.OrderStatus,
DeliveryDate = Convert.ToDateTime(dto.DeliveryDate),
CustomerId = oldCustomerId,
StoreId = oldStoreId,
Code = dto.Code
};
}
}
In your code I see that there are all sorts of Mocking and Initial test setups that is taking place without a clear intention on what to test.
Unit Test: What ?
Tests a unit of an application without its external dependencies
Unit Test: Why ?
Makes refactoring faster and ensures you don't break existing portion of your code
Unit Test: Steps ?
We first need to re-factor the code before we do unit tests. Modularity is the key
By using Interfaces remove the tight couplings in the code
Inject the dependency via method parameters, constructor, properties or use Dependency Injection
Consider using Mock objects, as a good practice, only when dealing with external dependency.
In the [TestMethod] we organize the tests into 3 categories Arrange -> Act -> Assert
Example:
//Arrange
var res = new Reservation();
//Act
var op = res.Method(new User{IsAdmin=true});
// Assert
Assert.IsTrue(op);
Naming Conventions in UnitTests:
TestProjectName:     [InserProjectName].UnitTests
TestClasses:         [InsertClassName]Tests
TestMethod:         [MethodYourTesting]_[Scenario]_[ExpectedBehavior]
I have created a Console app as close as possible to your problem
(minus the DBContext) that you can replicate on your PC to understand
the various portions.
All the domain classes are part of one single
file for the sake of testability to reproduce faster.
Console App Project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StackOrderProcessor
{
public class CustomersOrder
{
public OrderDto Order { get; set; }
public List<CustomersOrder> CustomersOrders = new List<CustomersOrder>();
public DateTime OrderDate { get; set; }
public string OrderStatus { get; set; }
public int CustomerID { get; set; }
public int Code { get; set; }
public int ID { get; set; }
}
public class Customer
{
public OrderDto Order { get; set; }
public List<Customer> Customers = new List<Customer>();
public int Code { get; set; }
public int ID { get; set; }
}
public class OrderDto
{
public DateTime OrderDate { get; set; }
public int CustomerCode { get; set; }
public string OrderStatus { get; set; }
public int Code { get; set; }
}
public interface IRepository
{
int GetOldCustomerId(int customerCode);
int GetOldOrderId(int orderCode);
void SaveCustomer(Customer customer);
void SaveOrder(CustomersOrder order);
}
public class Repository : IRepository
{
private readonly Customer _cust;
private readonly CustomersOrder _custOrder;
public Repository(Customer cust, CustomersOrder custOrder )
{
_cust = cust;
_custOrder = custOrder;
}
public int GetOldCustomerId(int customerCode)
{
var cuId = _cust.Customers.First(e => e.Code == customerCode);
return cuId.ID;
}
public int GetOldOrderId(int orderCode)
{
var oId = _custOrder.CustomersOrders.FirstOrDefault(e => e.Code == orderCode);
return oId.ID;
}
public void SaveCustomer(Customer customer)
{
_cust.Customers.Add(customer);
}
public void SaveOrder(CustomersOrder order)
{
_custOrder.CustomersOrders.Add(order);
}
}
public class OrderProcess
{
private readonly IRepository _repository;
public OrderProcess(IRepository repository)
{
_repository = repository;
}
public void Process(CustomersOrder order)
{
var oldOrder = _repository.GetOldOrderId(order.Code);
if (oldOrder == 0)
_repository.SaveOrder(order);
}
}
public class OrderBuilder
{
private readonly IRepository _repository;
public OrderBuilder(IRepository repository)
{
_repository = repository;
}
public CustomersOrder OrderBuild(OrderDto dto)
{
var oldCustomerId = _repository.GetOldCustomerId(dto.CustomerCode);
return new CustomersOrder()
{
Order = dto,
OrderDate = Convert.ToDateTime(dto.OrderDate),
OrderStatus = dto.OrderStatus,
ID = oldCustomerId,
CustomerID = oldCustomerId,
Code = dto.Code
};
}
}
class Program
{
static void Main(string[] args)
{
var cust = new Customer();
var custOrder = new CustomersOrder();
#region PopulatingCustomer
//Populating OrderDto
var dto1 = new OrderDto { Code = 1, CustomerCode = 1, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
//Populating Customer
var customerList = cust.Customers = new List<Customer>();
var customerOrderList = custOrder.CustomersOrders = new List<CustomersOrder>();
var customer1 = new Customer
{
Code = 1,
ID = 1, Order=dto1
};
var customer2 = new Customer
{
Code = 2,
ID = 2,
};
customerList.Add(customer1);
customerList.Add(customer2);
#endregion
#region PopulatingCustomerOrder
var customersOrder1 = new CustomersOrder { Code = 1, CustomerID = 1, ID = 1, Order = dto1, OrderDate = dto1.OrderDate, OrderStatus = dto1.OrderStatus };
customerOrderList.Add(customersOrder1);
#endregion
#region InvokingMethods
//IRepository
IRepository IRepo = new Repository(cust,custOrder);
//OrderProcessor
var orderProcesor = new OrderProcess(IRepo);
//OrderBuilder
var dto2 = new OrderDto { Code = 2, CustomerCode = 2, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
var oBuilder = new OrderBuilder(IRepo);
var newCustOrder = oBuilder.OrderBuild(dto2);
customerOrderList.Add(newCustOrder);
#endregion
Console.Read();
}
}
}
UnitTest Project
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using StackOrderProcessor;
namespace StackOrderProcessor.UnitTests
{
[TestClass]
public class RepositoryTests
{
[TestMethod]
public void GetOldCustomerId_WhenCalled_ReturnsOId()
{
//Arrange
var cust = new Customer();
var custOrder = new CustomersOrder();
IRepository repo = new Repository(cust,custOrder);
var customerList = cust.Customers = new List<Customer>();
var dto1 = new OrderDto { Code = 1, CustomerCode = 1, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
var customer1 = new Customer
{
Code = 1,
ID = 1,
Order = dto1
};
var customer2 = new Customer
{
Code = 2,
ID = 2,
};
customerList.Add(customer1);
customerList.Add(customer2);
//Act
repo.GetOldCustomerId(1);
//Assert
Assert.AreEqual(1, 1); //Test will Pass as we have a customer of Code 1
}
[TestMethod]
//MethodName_Scenario_Expectedbehavior
public void SaveCustomer_WhenCalled_AddsNewCustomer()
{
var cust = new Customer();
var custOrder = new CustomersOrder();
IRepository repo = new Repository(cust, custOrder);
var customerList = cust.Customers = new List<Customer>();
var dto1 = new OrderDto { Code = 1, CustomerCode = 1, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
var customer1 = new Customer
{
Code = 1,
ID = 1,
Order = dto1
};
var customer2 = new Customer
{
Code = 2,
ID = 2,
};
customerList.Add(customer1);
customerList.Add(customer2);
//Act
var custToSave = new Customer
{
Code = 3,
ID = 3,
Order = null
};
repo.SaveCustomer(custToSave);
//Assert
Assert.AreEqual(3, customerList.Count);
}
}
[TestClass]
public class OrderProcessor1Tests
{
[TestMethod]
public void Process_WhenOrderIsZero_AddsNewCustomerOrder()
{
//Arrange
var cust = new Customer();
var custOrder = new CustomersOrder();
var customerOrderList = custOrder.CustomersOrders = new List<CustomersOrder>();
IRepository repo = new Repository(cust, custOrder);
var orderProcessor = new OrderProcess(repo);
var dto1 = new OrderDto { Code = 1, CustomerCode = 1, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
var custOrder1 = new CustomersOrder { ID = 1, Code = 1, CustomerID = 1, Order = dto1, OrderDate = dto1.OrderDate, OrderStatus = dto1.OrderStatus };
customerOrderList.Add(custOrder1);
//Act
orderProcessor.Process(custOrder1);
//Assert
Assert.AreEqual(1, customerOrderList.Count);
}
}
}
Note: Make sure to add reference of StackOrderProcessor in StackOrderProcessor.UnitTests
You will still need to better organize the Unit Test Methods, this was just for demonstration purposes, I hope concepts are much more clear now
Your question doesn't have enough information, you don't need your repository code for this question, but OrderBuiler class and _orders field needs. I'm sorry for this comment in answers location.

how i can test my data annotation field in core web api?

I try to create the tests for my API controller method. In a simple way, I write the add method.
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> AddAsync([FromBody]BaseUserDTO dto)
{
if (ModelState.IsValid)
{
return Ok();
}
else
{
return ValidationProblem();
}
}
in dto model I have
public class BaseUserDTO
{
[Required(ErrorMessage = "This field should be filled in", AllowEmptyStrings = false)]
[RegularExpression(#"(^[a-zA-Z0-9_ -]+$)", ErrorMessage = ("Use only Latin characters"))]
public string FirstName { get; set; }
[Required(ErrorMessage = "This field should be filled in", AllowEmptyStrings = false)]
[RegularExpression(#"(^[a-zA-Z0-9_ -]+$)", ErrorMessage = ("Use only Latin characters"))]
public string LastName { get; set; }
}
I wrote the first try to test the data annotation
[Fact]
public async Task UserValidationError()
{
//Arrange
BaseUserDTO userDTO = new BaseUserDTO
{
FirstName = "222A###",
LastName = "Test",
Email = "Test#test.com",
PhoneNumber = "(111)111-1111",
Role = 0,
Password = "1234567A",
RetypePassword = "1234567A"
};
UserController controller = new UserController(userServicesMock.Object, mapperMock.Object, loggerMock.Object);
//Act
IActionResult result = await controller.AddAsync(userDTO);
//Assert
Assert.IsType<BadRequestObjectResult>(result);
}
but the model state always true, and I don't understand why it happened????
My second try take NullReference in mongo connection when startup started (in a normal situation it works good(when the application works), check it by postman)
[Fact]
public async Task UserValidationError(string userState)
{
//Arrange
BaseUserDTO userDTO = new BaseUserDTO
{
FirstName = "222A###",
LastName = "Test",
Email = "Test#test.com",
PhoneNumber = "(111)111-1111",
Role = 0,
Password = "1234567A",
RetypePassword = "1234567A"
};
var b = new WebHostBuilder().UseStartup<Startup>().UseEnvironment("development");
var server = new TestServer(b) { BaseAddress = new Uri(#"http://localhost:54133") };
var client = server.CreateClient();
var json = JsonConvert.SerializeObject(userDTO);
var content = new StringContent(json, Encoding.UTF8, "application/json");
UserController controller = new UserController(userServicesMock.Object, mapperMock.Object, loggerMock.Object);
//Act
var result = await client.PostAsync("api/User", content);
//assert
Assert.Equal(400, (int)result.StatusCode);
}
How normally create the unit test to check the DataAnnotation validation? Or how right check this validation?
using System.ComponentModel.DataAnnotations;
/*other using*/
[Fact]
public void UserValidationError()
{
//Arrange
BaseUserDTO userDTO = new BaseUserDTO
{
FirstName = "222A###",
LastName = "Test",
Email = "Test#test.com",
PhoneNumber = "(111)111-1111",
Role = 0,
Password = "1234567A",
RetypePassword = "1234567A"
};
//ACT
var lstErrors = ValidateModel(userDTO);
//ASSERT
Assert.IsTrue(lstErrors.Count == 1);
//Or
Assert.IsTrue(lstErrors.Where(x => x.ErrorMessage.Contains("Use only Latin characters")).Count() > 0);
}
//http://stackoverflow.com/questions/2167811/unit-testing-asp-net-dataannotations-validation
private IList<ValidationResult> ValidateModel(object model)
{
var validationResults = new List<ValidationResult>();
var ctx = new ValidationContext(model, null, null);
Validator.TryValidateObject(model, ctx, validationResults, true);
return validationResults;
}
More details in Microsoft Site : https://learn.microsoft.com/en-us/aspnet/web-api/overview/testing-and-debugging/unit-testing-controllers-in-web-api

How do you test a method to see if it returns a PagedViewModel<AlertModel>()?

I have a handler class that takes in a Query class with 3 properties. The handler returns a PagedViewModel object. I am trying to test that this handler is returning what it is supposed to return, but I cannot get my test method to work properly.
I attempted to create a PagedViewModel and assert that the test viewModel and the actual viewModel were equal but this is not returning what I would expect. (It is just a regular PagedViewModel not a Mock).
My test results look identical, so I am confused as to what the problem is.
My handler
protected override PagedViewModel<AlertModel> HandleCore(AlertsByOrgQuery request)
{
List<AlertModel> alertsModel = new List<AlertModel>();
List<long> alertTypes = new List<long>();
Expression<Func<Alert, bool>> query = PredicateBuilder.True<Alert>();
if (request.AlertTypes?.Any() == true) {
foreach (var alertType in request.AlertTypes) {
alertTypes.Add((int)alertType);
}
}
PagedList<Alert> pagedAlerts;
try {
var alertsQuery = BuildQuery(request, alertTypes);
pagedAlerts = new PagedList<Alert>(alertsQuery, request.Page, request.Rows);
} catch (Exception ex) {
_logger.Error("Error loading alerts.", ex);
return null;
}
var viewModel = new PagedViewModel<AlertModel>();
viewModel.PageNumber = pagedAlerts.PageNumber;
viewModel.TotalRecordCount = pagedAlerts.TotalItemCount;
viewModel.NumOfPages = pagedAlerts.PageCount;
viewModel.Rows = pagedAlerts.Select(a => new AlertModel
{
Id = a.Id,
TimeStamp = a.TimeStamp,
Message = a.Message,
EntityType = DataEntity.EnumDescription((HIMS.Entities.Alert.AlertType)Convert.ToInt32(a.EntityType))
});
return viewModel;
}
My query class
public class AlertsByOrgQuery : DataPageModel, IRequest<PagedViewModel<AlertModel>>
{
public bool ShowUnread { get; set; }
public IEnumerable<HIMS.Entities.Alert.AlertType> AlertTypes { get; set; }
public HIMS.Entities.Authorization Authorization { get; set; }
}
My Test Method
public async Task HandleCoreGivenValidRequestShouldReturnViewModel() {
//arrange
var repo = new OptionalOrgAuthorizableRepo<Alert>(_mockDb.Object, _auth.OrganizationId);
var query = PredicateBuilder.True<Alert>();
var _testAlerts = repo.Get(query);
PagedList<Alert> pagedAlerts = new PagedList<Alert>(_testAlerts.AsQueryable(), 2, 3);
_mockViewModel = new PagedViewModel<AlertModel>();
_mockViewModel.PageNumber = pagedAlerts.PageNumber;
_mockViewModel.TotalRecordCount = pagedAlerts.TotalItemCount;
_mockViewModel.NumOfPages = pagedAlerts.PageCount;
_mockViewModel.Rows = pagedAlerts.Select(a => new AlertModel {
Id = a.Id,
TimeStamp = a.TimeStamp,
Message = a.Message,
EntityType = DataEntity.EnumDescription((Entities.Alert.AlertType)Convert.ToInt32(a.EntityType))
});
var handler = new AlertsByOrgHandler(_mockLogger.Object, _mockDb.Object);
var request = new AlertsByOrgQuery() {
ShowUnread = false,
AlertTypes = new List<Entities.Alert.AlertType> { (Entities.Alert.AlertType)Alert.AlertType.Case },
Authorization = _auth,
SIdx = "EntityType",
SOrd = "desc",
Page = 2,
Rows = 3
};
//act
var actual = await handler.Handle(request, new CancellationToken());
//assert
Assert.AreEqual(_mockViewModel, actual);
}
}

Categories

Resources