Finding difficulty in unit testing a Controller Action method using NUnit - c#

I want to Unit test the method ExecLogin() using NUnit testing framework. But I'm having problem while writing code for the testing because the GenerateInput() method is declared as internal virtual. So, I'm not being able pass the SessionUserId parameter to it which I think is needed. Please guide me how to write the unit test code for ExecLogin(). I'm new to testing.
This is related to ASP.NET MVC3 testing controller actions.
public class BaseController : Controller
{
public string SessionUserId
{
get { return Session["UserId"] as string; }
set { Session["UserId"] = value; }
}
internal virtual SomeType GenerateInput(SomeType inputData)
{
var finalInput = new StringBuilder(600);
finalInput.Append("<Root>")
.Append("<UserId>")
.Append(SessionUserId)
.Append("</UserId>")
.Append("<IPAddress>")
.Append(this.GetClientIpAddress())
.Append("</IPAddress>")
.Append(inputData.InputValue)
.Append("</Root>");
inputData.InputValue = finalInput.ToString();
return inputData;
}
}
public class LoginController : BaseController
{
[HttpPost]
public JsonResult ExecLogin(JsonRequest<LoginModel> request)
{
var loginObj = request.InputObject;
var login = new StringBuilder(300);
login.Append("<UserName>").Append(loginObj.UserName).Append("</UserName>")
.Append("<Password>").Append(EncodingHelper.GetHashedPassword(loginObj.Password)).Append("</Password>")
.Append("<RememberMe>").Append(loginObj.RememberMe).Append("</RememberMe>")
;
var input = new SomeType { Operation = request.Operation, PageName = ActionName, InputValue = login.ToString() };
var returnValue = SomeDelegate.Instance.ExecuteOperation(GenerateInput(input));
return Json(new JsonResponse<string> { Status = returnValue.Status, Result = this.PopulateSession(returnValue) });
}
}
This is our model classes:
public class LoginModel
{
public string UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public bool RememberMe { get; set; }
public bool IsValidUser { get; set; }
}
public class JsonRequest<T>
where T : class
{
public string Operation { get; set; }
public T InputObject { get; set; }
}
While learning Dependency Injection pattern I came to know that use of concrete classes makes code more tightly coupled. And the more tightly coupled the code the harder it becomes to test. Is this why I'm not being able to test it properly? Please help.

This is actually part of a common pattern, how to provide additional hook points for testing without disturbing the interface that is publicly available, and fortunately internal is your friend here.
I assume the problem is that you have 2 assemblies, let's call them MyCode.dll and MyCode.Tests.dll for simplicity. This means that MyCode.Tests cannot access the internal methods of MyCode because, well basically it isnt internal :-)
If you go to your AssemblyInfo.cs file for your MyCode project, you can add the following
[assembly:InternalsVisibleTo("MyCode.Tests")
This does exactly what it says, it makes your internals visible inside the MyCode.Tests code base. For more info see InternalsVisibleTo and Friend assemblies

Related

How to write an ASP.NET custom validator for a model defined in an external library

I'm trying to write a custom validation class for an ASP.NET Core web app I'm developing. I've found various examples of how to write custom client-side validation, such as this and this. These are all clear and make sense to me. However, my problem is that my model is defined within a .NET Standard library that other projects share. I cannot access the base classes I need to create the custom validation class from within this library.
Basically, I need to ensure that model.PropertyA is never greater than model.PropertyB. I'm aware that I could write some JavaScript that accomplishes this, but I'd prefer to utilize the existing ASP.NET Core validation techniques if possible.
I'd prefer to avoid any 3rd party dependencies to accomplish this, if possible.
hy,
Better to avoid Validation against Data Annotation because you don't have access to them in all cases , like the case you are describing;
One powerful package exist "FluentValidation "
you can create a model class and validate against properties
sample:
public class Person {
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
}
full documentation : https://docs.fluentvalidation.net/en/latest/aspnet.html
and then you add a validator for your commands like the following sample :
public class CreatePersonCommandValidator :
AbstractValidator<CreatePersonCommand>
{
....
public CreateTodoListCommandValidator(IApplicationDbContext context)
{
_context = context;
RuleFor(v => v.Name)
.NotEmpty().WithMessage("Name is required.")
.MaximumLength(200).WithMessage("Name must not exceed 200 characters.");
}...
....
..
You could build a class extends the class from libraries. And extends IValidatableObject to implement Validation.
Base class is from librarie.
public class Base
{
public int PropertyA { get; set; }
public int PropertyB { get; set; }
}
MyClass is build for validation.
public class MyClass : Base, IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (PropertyA > PropertyB)
{
yield return new ValidationResult(
$"model.PropertyA {PropertyA} can't greater than model.PropertyB ." );
}
}
}
Test codes:
[HttpPost]
public IActionResult Add([FromBody]MyClass myClass)
{
if (ModelState.IsValid)
{
RedirectToAction("Index");
}
return View();
}
Test result:
<div asp-validation-summary="ModelOnly" class="text-danger"></div>

How to get test initialize in memory and use in each test

I'm trying to create Unit Test. I have class User:
public class User
{
public int UsersCount
{
get
{
using (MainContext context = new MainContext())
{
return context.Users.Count();
}
}
}
public Guid Id { get; set; } = Guid.NewGuid();
public string UserName { get; set; }
public string Password { get; set; }
public Contact UserContact { get; set; }
}
My first test is UsersCount_Test test which tests UsersCount property:
[TestMethod]
public void UsersCount_Test()
{
var user = new User();
var context = new MainContext();
int usersCount = context.Users.Count();
context.Users.Add(new User());
context.SaveChanges();
Assert.AreEqual(usersCount + 1, user.UsersCount, $"It should be {usersCount + 1} because we're adding one more user");
}
If I add new test method in my test class (I'm using separate classes for testing each entity), I need to create new instance of User. That's why I did this:
public class BaseTest<T>
{
public T TestEntity;
public MainContext TestContext = new MainContext();
}
Now each test classes inherits from this class. And also I created test initializer method. Now my test class looks like this :
[TestClass]
public class UserTest : BaseTest<User>
{
[TestMethod]
public void UsersCount()
{
int usersCount = TestContext.Users.Count();
TestContext.Users.Add(new User());
TestContext.SaveChanges();
Assert.AreEqual(usersCount + 1, TestEntity.UsersCount, $"It should be {usersCount + 1} because we're adding one more user");
}
[TestInitialize]
public void SetTestEntity()
{
TestEntity = new User();
}
}
Now I'm adding new property to User and writing some logic:
string phoneNumber;
public string PhoneNumber { get { return phoneNumber; } set { SetUserContact(phoneNumber, value); phoneNumber = value; } }
void SetUserContact(string oldContact, string newContact)
{
UserContact.ContactsList.Remove(oldContact);
UserContact.ContactsList.Add(newContact);
}
After that I'm creating new test :
[TestMethod]
public void ContactList_Test()
{
var newPhone = "+8888888888888";
TestEntity.PhoneNumber = newPhone;
Assert.IsTrue(TestEntity.UserContact.ContactsList.Any(a => a == newPhone), $"It should contains {newPhone}");
}
Test fails because UserContact of TestEntity is null. I understood that TestEntity should be created by logic. After that I fix test initilizer method:
[TestInitialize]
public void SetTestEntity()
{
TestEntity = new User() { UserContact = new Contact() };
}
Here is Contact model
public class Contact
{
public Guid Id { get; set; } = Guid.NewGuid();
public virtual List<string> ContactsList { get; set; } = new List<string>();
}
My question is how to set TestEntity only one time, is it possible (maybe get it in memory and use it when it calls SetTestEntity method)? Because SetTestentity method creates a new entity in each test and it takes more development time. (For example, If creating an instance of UserContact takes 3 seconds all, test runs more than 3 seconds). Another way, in this case, is to set UserContact in ContactLists test, but I think it's not a good idea. In the future when we will add new logics, I need to fix each test. Please give me any suggestion and/or ideas.
If you would really have to TestInitialize runs before each test. You could use ClassInitialize to run test initialization for class only once.
BUT
From what I'm seeing your performance issue is caused by desing and architecutre of your application where you are breaking single responsibility principle. Creating static database entity or sharing it across test is not a solution it is only creating more technical debt. Once you share anything across test it has to be maintained acorss test AND by definition unit test SHOULD run separately and independently to allow testing each scenarion with fresh data.
You shouldn't be creating database models that depend on MainContext. Should single User really know how many Users there are in the database? If not then please create separate repository that will have MainContext injected and method GetUsersCount() and unit test that with InMemoryDatabase by adding few users calling specific implementation and checking if correct number of users has been added, like following:
public interface IUsersRepository
{
int GetUsersCount();
}
public class UsersRepository : IUsersRepository
{
private readonly EntityFrameworkContext _context;
public UsersRepository(EntityFrameworkContext context)
{
_context = context;
}
public int GetUsersCount()
{
return _context.Users.Count();
}
}
Later only methods that are really using context should be tested withInMemoryDatabase and for methods that are making use of IUserRepository each specific method should be mocked since it is tested separatly.
TestInitialize and TestCleanup are ran before and after each test, this is to ensure that no tests are coupled.
If you want to run methods before and after ALL tests only once, decorate relevant methods with the ClassInitialize and ClassCleanup attributes.
You can use the following additional attributes as you write your tests:
Sample code-
// Use ClassInitialize to run code before running the first test in the class
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext) { }
// Use ClassCleanup to run code after all tests in a class have run
[ClassCleanup()]
public static void MyClassCleanup() { }
// Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize() { }
// Use TestCleanup to run code after each test has run
[TestCleanup()]
public void MyTestCleanup() { }
Basically you can have your SetEntity method in your ClassIntialize method
Hope it helps.

Designing Viewmodels and avoid if else statements in controllers and write good business logic asp.net web api using design patterns

I have a web api action method which takes below Model as parameter (Post).
public class RequestModel
{
public string PartType { get; set; }
public int Quantity { get; set; }
public decimal UnitCost{ get; set; }
public bool? Owner { get; set; }
public bool? DoSplit { get; set; }
}
The options Owner/Do Split will be choosen by the user on UI and its based on Part Type. Also based on the Owner flag there is some other business logic which needs to be executed in combination with the DoSplit and Quantity. Hence I have many permuations and combinations. Going bruteforce the logic would go this way:
int existingQty = GetInitialQuantity(model.SerialId); //returns esisting qty
if(existingQty < model.Quantity && model.Owner)
{
// logic here
}
else if (existingQty < model.Quantity && model.Owner == false)
{
}
else if (existingQty = model.Quantity) // no need to check for DoSplit
{
}
etc..... more if else in combincation with qty comaprison, Dosplit and owner flag checks with null checks.
based on the different property values in the model (in combination) I need to do different actions. How to avoid if else and use a proper design patterns of C# here.
Since the model is passed from javascript through a web api call to my action method how can I use OOPs here for the requestmodel and avoid branching in the controller method ?
I think one of the main reasons that you have so much if/else is that you do not have the business logic in the object itsel but try to use the business logic from outside. As I do not get what your business logic is, my implementation might not work on your case, but i want to show you how to get rid of the if else in a simple case. The main goal is to not use the properties but only use the functions and let the object handle its state on its own. (lookup Tell dont ask and State Pattern)
lets look at this class
public class User
{
string name { get; set; }
bool isDisabled { get; set; }
}
using it might be like this
if (!user.isDisabled)
{
user.name = nameFromApi
}
but in this case you have to repeat this on every corner where you want to use the User. So consider this
public interface IUser
{
string name { get; }
IUser updateName(string newName);
IUser disableUser();
}
public class DisabledUser : IUser
{
public DisabledUser(IUser activeUser)
{
this.name = activeUser.name;
}
public string name { get; }
public IUser updateName(string newName)
{
return this;
}
public IUser disableUser()
{
return new DisabledUser(this);
}
}
public class ActiveUser : IUser
{
public ActiveUser(IUser user)
{
this.name = user.name;
}
public string name { get; private set; }
public IUser updateName(string newName)
{
this.name = newName;
return this;
}
public IUser disableUser()
{
return new DisabledUser(this);
}
}
In this way the if is gone and you actually gained something else: You can easily extend the implementation with other states like banned and you do not have to change the old implementation. Yes, it is more code, but way easier to maintain.
In you case i think you should be able to get rid of all the if/elses regarding the boolean flags, if you initialize the objects correctly. This is a powerfull pattern and you do not need to cast anything to be able to use the user.
I do not know your usecase for the quantity stuff, so I can not tell you how this might get resolved, but there is certainly a way to do that.

Using Unity to get objects based on name alone

I have an app with a handler method. The handler method gets a json string which includes the name of the object that needs to handle the request and the parameters for the request. Basically, something (I'll keep it simple) like this:
public interface IJob
{
bool Execute();
bool Hydrate(string source);
}
public class JobBase
{
public int Id { get; set; }
public JobType JobType { get; set; }
public CronExpression CronExpression { get; set; }
}
public class JobSubmitClone : JobBase, IJob
{
public string[] Tokens { get; set; }
public bool Hydrate(string source)
{
// code omitted...
return true;
}
public bool Execute()
{
// code omitted...
return true;
}
}
IJob and JobBase are both kept in a Common class project. All apps reference this DLL.
In my main app I have Unity installed and one of the steps in loading the container is accomplished like:
// Scan assemblies for Job definitions...
_container.RegisterTypes(AllClasses.FromAssembliesInBasePath().
Where(type => typeof(IJob).IsAssignableFrom(type)),
WithMappings.FromAllInterfaces,
WithName.TypeName,
WithLifetime.Transient);
Each "Job" is defined in its own class project and is NOT referenced by the main app. Each "Job" must inherit from JobBase and IJob.
The main app has a simple REST service exposed. You can post something like:
{ jobName : JobSubmitClone, Id : 1, JobType : 2, CronExpression : '' }
In the main app I am trying to pull the object from the container based on JobName. I've tried this (yes, I know it violates the IoC pattern):
var container = UnityHelpers.GetConfiguredContainer();
var job = container.Resolve<IJob>(myParams.jobName); // "JobSubmitClone" //
var hydrated = job.Hydrate(myParams);
if(hydrated)
var result = job.Execute();
I am getting the following error:
Exception is: InvalidOperationException - The current type, IJob, is
an interface and cannot be constructed. Are you missing a type
mapping?
What am I missing?
Each "Job" is defined in its own class project and is NOT referenced
by the main app. Each "Job" must inherit from JobBase and IJob.
Have you looked into MEF? It has the ability to query and load a class by its metadata. I tend to use Unity for known, compile-time dependencies and MEF for dynamic assemblies loaded at runtime. (There's no reason you can't use both in the same project.)
We do something similar to what you're looking for, I think. We load workflows based on their class name.
Just decorate the Job with a System.ComponentModel.Composition.MetadataAttribute....
[MetadataAttribute]
public class WorkflowMetadataAttribute : Attribute, IWorkflowMetadata
{
public WorkflowMetadataAttribute(string typeName) {
TypeName = typename;
}
public string TypeName { get; private set; }
}
Which you put on the thing you want to export....
public interface IWorkflow // aka IJob
{
void Execute();
}
[Export(typeof(IWorkflow))]
[WorkflowMetadata("WhateverWorkflow")]
public class WhateverWorkflow : IWorkflow
{
public void Execute() { }
}
The exported class can be built separately of the project that runs it. If you build it as a library into a separate assembly, you can load the assembly (or directory of assemblies) in an importer class.
public class WorkflowCatalog : IPartImportsSatisfiedNotification
{
[ImportMany]
public IEnumerable<Lazy<IWorkflow, IWorkflowMetadata>> Workflows { get; private set; }
public void Compose() {
var path = Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location );
var catalog = new DirectoryCatalog( path );
var compositionContainer = new CompositionContainer( catalog );
compositionContainer.ComposeParts(this);
}
public void OnImportsSatisfied() {
var workflow = Workflows.Single(w => w.Metadata.TypeName == "WhateverWorkflow").Value;
workflow.Execute();
}
}
IJob, IJobMetadata, and JobBase live in the core. Job classes live in their own libraries (or they can live in the main program too I suppose).
Turns out that there are a lot of ways to manipulate Unity. This is what ended up working so far:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().Where(type => typeof(IJob).IsAssignableFrom(type) && type.IsClass),
WithMappings.FromAllInterfaces,
t => t.IsNested ? t.DeclaringType.Name + "." + t.Name : t.Name,
WithLifetime.Transient);
I also built an extension method:
public static IJob Job(this string src)
{
var container = UnityConfig.GetConfiguredContainer();
var job = container.Resolve<IJob>(src);
return job;
}
I created a small model for the Minimum Payload:
public class MinimumCommandModel : IRequest<MinimumResultModel>
{
public MinimumCommandModel(string json)
{
FullPayloadString = json;
MinimumPayload = JsonConvert.DeserializeObject<MinimumPayload>(json);
}
public string MinimumPayloadString => JsonConvert.SerializeObject(MinimumPayload);
public string FullPayloadString { get; set; }
public MinimumPayload MinimumPayload { get; set; }
}
I can then directly get a job from a (JSON) sting payload:
var command = new MinimumCommandModel(Request.Content.ReadAsStringAsync().Result);
var job = command.MinimumPayload.JobName.Job();

Can ServiceStack services contain multiple methods?

Environment is Visual Studio 2012, ServiceStack, ASP.NET Web Application Project (followed https://github.com/ServiceStack/ServiceStack/wiki/Create-your-first-webservice)
Looking through some of the classes in ServiceStack.Examples, I noticed that most of the services contain only one method. Either some override on Execute() or, if a REST service, some override of OnPost/Get/Put/Delete().
How should I approach making a full API set, if I have tens of functions I need implemented RegisterUser(), RemoveUser(), AddFriend(), RemoveFriend() ... One service per method?
public RegisterUserService : IService<User> { public object Execute(User> dto) { ... } }
public RemoveUserService : IService<User> { public object Execute(User> dto) { ... } }
public AddFriendService : IService<Friend> { public object Execute(Friend dto) { ... } }
public RemoveFriendService: IService<RequestDTO4> { public object Execute(Friend dto) { ... } }
I'm pretty lost on how to begin implementing a full API set. I've read the first and second wiki page on 'Creating your first webservice', which I've copied to make 1 service method. But now I want to make 10 or 40 service methods and I'm not sure how to do that.
I noticed that implementing from IRestService<T> allows you up to 4 methods instead of the one Execute() method, simply because each method corresponds to a different HTTP verb. So is there something like that I could write? Basically something like:
public MyService : IService/IRestService/ServiceBase?<User>
{
public object AddUser(User user) { }
public object RemoveUser(User user) { }
public object ModifyUser(User user) { }
}
Just looking for something that doesn't necessarily have to contain all methods in one service class, but as many as reasonably possible ... do I really have to create 1 service for each service method?
Note on pursuing a strictly RESTful architecture: I only read up a little on REST, but it seems like I'd have to strictly follow rules like: treat everything as a resource even if you have to re-design your models, no verbs in the URL names (/Friends, not /GetFriends because REST gives you OnGet(), OnPost(), OnPut(), and OnDelete() ... basically I'm interested in the easiest, quickest, and most painless way of implementing a a few dozen service methods. It's a personal project, so the requirements won't vary too much.
Thanks in advance for guiding me through this first step.
EDIT: Just saw this related question: How to send commands using ServiceStack?
Mythz said there's no "ServiceStack way" to design. The guy's question is pretty much like mine. I'm wondering how to stack a lot of service methods in a service.
EDIT 2: Just saw Need help on servicestack implementation, and Separate or combined ServiceStack services?.
I just tested the code below successfully with working routes:
[Route("/registerUser/setEmail/{Email}")]
[Route("/registerUser/setPassword/{Password}")]
[Route("/registerUser/setPhoneNumber/{PhoneNumber}")]
[Route("/lalal2395823")]
[Route("/test3234/test23423511")]
public class RegisterUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Nickname { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
But what I'd like is for each [Route("path")] to go to a different method, instead of having them all parsed in Execute() and having to parse which string isn't null or empty.
My Solution
I decided to take Rickard's advice and make a proper REST API, because it seems simpler and cleaner in the end.
This is now my class using the new ServiceStack API (new as of 9/24/12):
using UserModel = Project.Model.Entities.User;
[Route("/User", "POST")]
[Route("/User/{FirstName}", "POST")]
[Route("/User/{FirstName}/{LastName}", "POST")]
[Route("/User/{FirstName}/{LastName}/{Nickname}", "POST")]
[Route("/User/{FirstName}/{LastName}/{Nickname}/{PhoneNumber}", "POST")]
[Route("/User/{FirstName}/{LastName}/{Nickname}/{PhoneNumber}/{Email}", "POST")]
public class CreateUser : IReturn<UserModel>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Nickname { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
public class CreateUserService : Service
{
public object Post(CreateUser request)
{
try
{
using (var session = FluentNHibernateHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var user = new UserModel()
{
FirstName = request.FirstName,
LastName = request.LastName,
Nickname = request.Nickname,
PhoneNumber = request.PhoneNumber,
Email = request.Email,
Password = request.Password,
};
session.SaveOrUpdate(user);
transaction.Commit();
return user;
}
}
}
catch
{
throw;
}
}
}
This is now a lot simpler with ServiceStack's new API Design released in (v3.9.15+).
#Rickard makes a lot of good points on how to re-structure your service so it's more REST-ful which is now easier to achieve with ServiceStack's new API which is now less restrictive and more flexible where the same service can handle multiple different Request DTOs and you're no longer restricted in the Response Type you can return.
Following the HTTP way you have to turn your way of thinking upside down. You need to think in terms of resources, i.e. users, friends, etc. Using HTTP you already have a finite set of methods, namely Get, Put, Post, and Delete.
Hence, the service API design could look like this:
RegisterUser() => POST /users
RemoveUser() => DELETE /users/{userid}
AddFriend() => POST /users/{userid}/friends
RemoveFriend() => DELETE /users/{userid}/friends/{friendid}
ModifyUser() => PUT /users/{userid}
etc.
To implement for example RemoveFriend in ServiceStack you could do like this:
public class UserFriendService : RestServiceBase<UserFriendRequest>
{
public override object OnPost(UserFriendRequest request)
{
// pseudo code
var user = GetUser(request.UserId);
var friend = GetUser(request.FriendId); // FriendId is a field in the HTTP body
user.Friends.Add(friend);
return HttpResult.Status201Created(user, ...);
}
//...
}
[Route("/users/{userId}/friends")]
public class UserFriendRequest
{
public string UserId { get; set; }
public string FriendId { get; set; }
}

Categories

Resources