How to test service layer which directly uses NHibernate? - nhibernate

Hello can anyone give me advice on how to test my service layer which uses NHibernate ISession directly?
public class UserAccountService : IUserAccountService
{
private readonly ISession _session;
public UserAccountService(ISession session)
{
_session = session;
}
public bool ValidateUser(string email, string password)
{
var value = _session.QueryOver<UserInfo>()
.Select(Projections.RowCount()).FutureValue<int>().Value;
if (value > 0) return true;
return false;
}
}
I opt to use NHibernate directly for simple cases like simple query,validations and creating/updating records in the database. Coz i dont want to have an abstraction like repository/dao layer on top of Nhibernate that will just add more complexity to my architecture.

You need to decide what you want to actually test on your Service Layer, regardless of the fact that you're using NH.
In your example, a good first test might be to test that the email and password that you pass into your service method is actually being used as a check in your session.
In this case, you'd simply need to stub your session variable and set up expectations using a mock framework of some kind (like Rhino Mocks) that would expect a pre-determined email and password, and then return an expected result.
Some pseudocode for this might look like:
void ValidateUser_WhenGivenGoodEmailAndPassword_ReturnsTrue()
{
//arrange
var stubbedSession = MockRepository.GenerateStub<ISession>();
stubbedSession
.Expect(x => x.Query<UserInfo>())
.Return(new List {
new UserInfo { Email = "johns#email.com", Password = "whatever" } });
var service = new UserAccountService(stubbedSession);
//act
var result = service.ValidateUser("johns#email.com", "whatever");
//assert
Assert.That(result, Is.True);
}

I think you'll find it difficult to test database interactions in a static way. I'd recommend delegating responsibilities to another layer (that layer that adds complexity that you mentioned) that can be mocked for testing purposes, if you deem the functionality important enough to test.

Related

How best to handle data fetching needed for FluentValidation

In the app I'm working on, I'm using Mediatr and its pipelines to handle database interaction, some minor business logic, validation, etc.
There's a few checks for things like access control I can handle in the pipeline, since I'm using a context object as described here https://jimmybogard.com/sharing-context-in-mediatr-pipelines/ to go from ASP.Net identity to a custom context object with user information and claims.
One problem I'm having is that since this application is multi-tenant, I need to ensure that even if an object exists, it belongs to that tenant, and the only way to be sure of that is to grab the object from the database and check it. It seems to me the validation shouldn't have side effects, so I don't want to rely on that to populate the context object. But then that pushes a bunch of validation down into the Mediatr handlers as they check for object existence, and so on, leading to a lot of repeated code. I don't really want to query the database multiple times since some queries can be expensive.
Another issue with doing the more complicated validation in the actual request handlers is getting what are essentially validation errors back out. Currently, if one of these checks fail I throw a ValidationException, which is then caught by middleware and turned into a ProblemDetails that's returned to the API caller. This is basically exceptions as flow control, and a validation failure really isn't "exceptional" anyhow.
The thoughts I'm having on how to solve this are:
Somewhere in the pipeline, when I'm building the context, include attempting to fetch the objects needed from the database. Validation then fails if any of these are null. This seems like it would make testing harder, as well as needing to decorate the requests somehow (or use reflection) so the pipeline can know to attempt to load these objects.
Have the queries in the validator, but use some sort of cache aware repository so when the same object is queried later, it's served from the cache, and not the database. The handlers would also use this cache aware repository (Currently the handlers interact directly with the EF Core DbContext to query). This then adds the issue of cache invalidation, which I'm going to have to handle at some point, anyhow (quite a few items are seldom modified). For testing, a dummy cache object can be injected that doesn't actually cache anything.
Make all the responses from requests implement an interface (or extend an abstract class) that has validation info, general success flags, etc. This can either be returned through the API directly, or have some pipeline that transforms failures into ProblemDetails. This would add some boilerplate to every response and handler, but avoids exceptions as flow control, and the caching/reflection issues in the other options.
Assume for 1 and 2 that any sort of race conditions are not an issue. Objects don't change owners, and things are seldom actually deleted from the database for auditing/accounting purposes.
I know there's no true one size fits all for problems like this, but I would like to know if there's additional options I'm missing, or any long term maintainability issues anyone with a similar pipeline has encountered if they went with one of these listed options.
We use MediatR IRequestPreProcessor for fetching data that we need both in RequestHandler and in FluentValidation validators.
RequestPreProcessor:
public interface IProductByIdBinder
{
int ProductId { get; }
ProductEntity Product { set; }
}
public class ProductByIdBinder<T> : IRequestPreProcessor<T> where T : IProductByIdBinder
{
private readonly IRepositoryReadAsync<ProductEntity> productRepository;
public ProductByIdBinder(IRepositoryReadAsync<ProductEntity> productRepository)
{
this.productRepository = productRepository;
}
public async Task Process(T request, CancellationToken cancellationToken)
{
request.Product = await productRepository.GetAsync(request.ProductId);
}
}
RequestHandler:
public class ProductDeleteCommand : IRequest, IProductByIdBinder
{
public ProductDeleteCommand(int id)
{
ProductId = id;
}
public int ProductId { get; }
public ProductEntity Product { get; set; }
private class ProductDeleteCommandHandler : IRequestHandler<ProductDeleteCommand>
{
private readonly IRepositoryAsync<ProductEntity> productRepository;
public ProductDeleteCommandHandler(
IRepositoryAsync<ProductEntity> productRepository)
{
this.productRepository = productRepository;
}
public Task<Unit> Handle(ProductDeleteCommand request, CancellationToken cancellationToken)
{
productRepository.Delete(request.Product);
return Unit.Task;
}
}
}
FluentValidation validator:
public class ProductDeleteCommandValidator : AbstractValidator<ProductDeleteCommand>
{
public ProductDeleteCommandValidator()
{
RuleFor(cmd => cmd)
.Must(cmd => cmd.Product != null)
.WithMessage(cmd => $"The product with id {cmd.ProductId} doesn't exist.");
}
}
I see nothing wrong with handling business logic validation in the handler layer.
Moreover, I do not think it is right to throw exceptions for them, as you said it is exceptions as flow control.
Introducing a cache seems like overkill for the use case too. The most reasonable option is the third IMHO.
Instead of implementing an interface you can use the nifty OneOf library and have something like
using HandlerResponse = OneOf<Success, NotFound, ValidationResponse>;
public class MediatorHandler : IRequestHandler<Command, HandlerResponse>
{
public async Task<HandlerResponse> Handle(
Command command,
CancellationToken cancellationToken)
{
Resource resource = await _userRepository
.GetResource(command.Id);
if (resource is null)
return new NotFound();
if (!resource.IsValid)
return new ValidationResponse(new ProblemDetails());
return new Success();
}
And then map it in your API Layer like
public async Task<IActionResult> PostAsync([FromBody] DummyRequest request)
{
HandlerResponse response = await _mediator.Send(
new Command(request.Id));
return response.Match<IActionResult>(
success => Created(),
notFound => NotFound(),
failed => new UnprocessableEntityResult(failed.ProblemDetails))
);
}

Writing an event based SignalR Notification Service using DBContext ChangeTracker - separation of concerns

I have a controller that modifies appointments in a calendar. I want to use my SignalR hub to notify users à la "User X changed {appointmentTitle}: List: {Property} {OriginalValue} {NewValue}"
I'm a beginner in C# (Syntax-wise it's ok, but OOP concepts are new); I'm trying to use events to achieve the above.
Below are the handlers and arguments, an extract from the controller and a summary of my questions.
Code is abbreviated!
EventArgs
public class AppointmentChangeEventArgs : EventArgs
{
public EntityState AppointmentState = EntityState.Unchanged;
public EntityEntry Entity = null;
public ScheduleData Appointment = null;
}
EventHandler
// maybe this could be just one, and let the consumer decide based on EntityState?
public EventHandler<AppointmentChangeEventArgs> AppointmentChanged;
public EventHandler<AppointmentChangeEventArgs> AppointmentAdded;
public EventHandler<AppointmentChangeEventArgs> AppointmentRemoved;
protected virtual void OnAppointment(AppointmentChangeEventArgs appointmentChangeEventArgs)
{
switch (appointmentChangeEventArgs.AppointmentState)
{
case EntityState.Added:
AppointmentAdded?.Invoke(this, appointmentChangeEventArgs);
break;
case EntityState.Deleted:
AppointmentRemoved?.Invoke(this, appointmentChangeEventArgs);
break;
case EntityState.Modified:
AppointmentChanged?.Invoke(this, appointmentChangeEventArgs);
break;
default:
break;
}
}
Controller
public async Task<IActionResult> Batch([FromBody] ScheduleEditParameters param)
switch (param.Action) {
case "insert":
await _dbContext.Appointments.AddAsync(appointment);
break;
case "update":
// .. get Appointment from DB
appointment.Subject = value.Subject;
appointment.StartTime = value.StartTime;
// ...
case "remove":
// .. get Appointment from DB
_dbContext.Appointments.Remove(appointment);
}
var modifiedEntries = _dbContext.ChangeTracker
.Entries()
.Where(x => x.State != EntityState.Unchanged && x.State != EntityState.Detached)
.Select(x => new AppointmentChangeEventArgs() { Entity = (EntityEntry) x.Entity, AppointmentState = x.State, Appointment = appointment })
.ToList();
if (modifiedEntries.Any())
{
var notificationService = new NotificationService(signalRHub, notificationLogger);
AppointmentAdded += notificationService.OnAppointmentChanged;
AppointmentChanged += notificationService.OnAppointmentChanged;
AppointmentRemoved += notificationService.OnAppointmentChanged;
}
await _dbContext.SaveChangesAsync();
Questions
Is it ok to use EntityEntry and EntityState in event arguments?
for each modified Entry, I can obtain _dbContext.Entry(modifiedEntry).Properties.Where(x => x.IsModified).ToList(); - but does this belong in the NotificationService class? In order to do that, I'd also need to pass the DbContext over to NotificationService.
Might there be a simpler way to achieve this? Adding and Removing handlers are easy ("User X has added|removed ... appointment {Title}"), but in order to figure out the exact changes I'll have to look at the modified properties.
I'd be grateful if you could provide an insight into how you would structure & handle this task. Thank you.
To start off, I would generally recommend you not to use events here. Events are something that may sound very useful but due to the way they work (synchronously), they aren’t really the best way to achieve this in a web context, especially in a primarily asynchronous framework like ASP.NET Core.
Instead, I would recommend you to simply declare your own type, e.g. IAppointmentChangeHandler like this:
public interface IAppointmentChangeHandler
{
Task AddAppointment(ScheduleData appointment);
Task UpdateAppointment(ScheduleData appointment);
Task RemoveAppointment(ScheduleData appointment);
}
Your NotificationService can just implement that interface to be able to handle those events (obviously just send whatever you need to send there):
public class NotificationService : IAppointmentChangeHandler
{
private readonly IHubContext _hubContext;
public NotificationService(IHubContext hubContext)
{
_hubContext = hubContext;
}
public AddAppointment(ScheduleData appointment)
{
await _hubContext.Clients.InvokeAsync("AddAppointment", appointment);
}
public UpdateAppointment(ScheduleData appointment)
{
await _hubContext.Clients.InvokeAsync("UpdateAppointment", appointment);
}
public RemoveAppointment(ScheduleData appointment)
{
await _hubContext.Clients.InvokeAsync("RemoveAppointment", appointment);
}
}
And inside of your controller, you just inject that IAppointmentChangeHandler then and call the actual method on it. That way you have both the controller and the notification service completely decoupled: The controller does not need to construct the type first and you also do not need to subscribe to some events (which you would also have to unsubscribe from at some point again btw). And you can leave the instantiation completely to the DI container.
To answer your individual questions:
Is it ok to use EntityEntry and EntityState in event arguments?
I would avoid using it in a context outside of your database. Both are an implementation detail of your database setup, since you are using Entity Framework here. Not only would this couple your event handlers strongly with Entity Framework (meaning that everyone that wanted to be an event handler would need to reference EF even if they didn’t do anything with it), you are also leaking possibly internal state that may change later (you don’t own the EntityEntry so who knows what EF does with it afterwards).
for each modified Entry, I can obtain _dbContext.Entry(modifiedEntry).Properties.Where(x => x.IsModified).ToList();
If you look at your code, you are first calling Add, Update or Remove on your database set; and then you are using some logic to look at some internal EF stuff to figure out the exact same thing really. You could make this a lot less complex if you constructed the AppointmentChangeEventArgs within those three switch cases directly.
but does this belong in the NotificationService class? In order to do that, I'd also need to pass the DbContext over to NotificationService.
Does a notification service have anything to do with a database? I would say no; unless you are persisting those notifications into the database. When I think about a notification service, then I expect to be able to call something on it to actively trigger a notification, instead of having some logic within the service to figure out what notifications it could possibly trigger.
Might there be a simpler way to achieve this? Adding and Removing handlers are easy ("User X has added|removed ... appointment {Title}"), but in order to figure out the exact changes I'll have to look at the modified properties.
Think about it in the simplest way first: Where do you update the values of the database entity? Within that update case. So at that point, where you are copying over values from the passed object, you can also just check which properties you are actually changing. And with that, you can record easily which properties you need to notify about.
Decouple this completely from EF and you will be a lot more flexible in the long run.

UserNamePasswordValidator and Session Management

I'm using WCF custom Validator with HTTPS (.NET 4.5). Validate on success returns Customer object which I would like to use later. Currently I'm able to do it with Static variables which I like to avoid if possible. I tried to use HttpContext which becomes null in main thread. My understanding Validate runs under different thread. Is there any way I could share session info without involving DB or File share. See related threads here and here.
In Authentication.cs
public class CustomValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
//If User Valid then set Customer object
}
}
In Service.cs
public class Service
{
public string SaveData(string XML)
{
//Need Customer object here. Without it cannot save XML.
//HttpContext null here.
}
}
I can suggest you an alternative approach. Assuming that the WCF service is running in ASP.Net compatibility mode and you are saving the customer object to session storage. Create a class such as AppContext
The code would look something like this
public class AppContext {
public Customer CurrentCustomer {
get {
Customer cachedCustomerDetails = HttpContext.Current.Session[CUSTOMERSESSIONKEY] as Customer;
if (cachedCustomerDetails != null)
{
return cachedCustomerDetails;
}
else
{
lock (lockObject)
{
if (HttpContext.Current.Session[CUSTOMERSESSIONKEY] != null) //Thread double entry safeguard
{
return HttpContext.Current.Session[CUSTOMERSESSIONKEY] as Customer;
}
Customer CustomerDetails = ;//Load customer details based on Logged in user using HttpContext.Current.User.Identity.Name
if (CustomerDetails != null)
{
HttpContext.Current.Session[CUSTOMERSESSIONKEY] = CustomerDetails;
}
return CustomerDetails;
}
}
}
}
The basic idea here is to do lazy loading of data, when both WCF and ASP.Net pipelines have executed and HTTPContext is available.
Hope it helps.
Alright this should have been easier. Since the way UserNamePasswordValidator works, I needed to use custom Authorization to pass UserName/Password to the main thread and get customer info again from the database. This is an additional DB call but acceptable workaround for now. Please download code from Rory Primrose's genius blog entry.

MVC 3/EF repository pattern and proper data access

Being rather new to MVC 3 and EF, I'm trying to understand the best architectural approach to developing an application for my company. The application will be a large-scale application that potentially handles hundreds of users at the same time, so I want to make sure I understand and am following proper procedures. So far, I've determined that a simple repository pattern (such as Controller -> Repository -> EF) approach is the best and easiest to implement, but I'm not sure if that is definitely the best way to do things. The application will basically return data that is shown to a user in a devexpress grid and they can modify this data/add to it etc.
I found this article and it is rather confusing for me at this time, so I'm wondering if there is any reason to attempt to work with a disconnected EF and why you would even want to do so: http://www.codeproject.com/Articles/81543/Finally-Entity-Framework-working-in-fully-disconne?msg=3717432#xx3717432xx
So to summarize my question(s):
Is the code below acceptable?
Should it work fine for a large-scale MVC application?
Is there a better way?
Will unnecessary connections to SQL remain open from EF? (SQL Profiler makes it look like it stays open a while even after the using statement has exited)
Is the disconnected framework idea a better one and why would you even want to do that? I don't believe we'll need to track data across tiers ...
Note: The repository implements IDisposable and has the dispose method listed below. It creates a new instance of the entity context in the repository constructor.
Example Usage:
Controller (LogOn using Custom Membership Provider):
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
User newUser = new User();
using (AccountRepository repo = new AccountRepository())
{
newUser = repo.GetUser(model.UserName);
...
}
}
Membership Provider ValidateUser:
public override bool ValidateUser(string username, string password)
{
using (AccountRepository repo = new AccountRepository())
{
try
{
if (string.IsNullOrEmpty(password.Trim()) || string.IsNullOrEmpty(username.Trim()))
return false;
string hash = FormsAuthentication.HashPasswordForStoringInConfigFile(password.Trim(), "md5");
bool exists = false;
exists = repo.UserExists(username, hash);
return exists;
}catch{
return false;
}
}
}
Account Repository Methods for GetUser & UserExists:
Get User:
public User GetUser(string userName)
{
try
{
return entities.Users.SingleOrDefault(user => user.UserName == userName);
}
catch (Exception Ex)
{
throw new Exception("An error occurred: " + Ex.Message);
}
}
User Exists:
public bool UserExists(string userName, string userPassword)
{
if (userName == "" || userPassword == "")
throw new ArgumentException(InvalidUsernamePassword);
try
{
bool exists = (entities.Users.SingleOrDefault(u => u.UserName == userName && u.Password == userPassword) != null);
return exists;
}
catch (Exception Ex)
{
throw new Exception("An error occurred: " + Ex.Message);
}
}
Repository Snippets (Constructor, Dispose etc):
public class AccountRepository : IDisposable
{
private DbContext entities;
public AccountRepository()
{
entities = new DbContext();
}
...
public void Dispose()
{
entities.Dispose();
}
}
What's acceptable is pretty subjective, but if you want to do proper data access I suggest you do NOT use the repository pattern, as it breaks down as your application gets more complex.
The biggest reason is minimizing database access. So for example look at your repository and notice the GetUser() method. Now take a step back from the code and think about how your application is going to be used. Now think about how often you are going to request data from the user table without any additional data. The answer is almost always going to be "rarely" unless you are creating a basic data entry application.
You say it your application will show a lot of grids. What data is in that Grid? I'm assuming (without knowing your application domain) that the grids will combine user data with other information that's relevant for that user. If that's the case, how do you do it with your repositories?
One way is to call on each repository's method individually, like so:
var user = userRepository.GetUser("KallDrexx");
var companies = companyRepository.GetCompaniesForUser(user.Id);
This now means you have 2 database calls for what really should be just one. As your screens get more and more complex, this will cause the number of database hits to increase and increase, and if your application gets significant traffic this will cause performance issues. The only real way to do this in the repository pattern is to add special methods to your repositories to do that specific query, like:
public class UserRepository
{
public User GetUser(string userName)
{
// GetUser code
}
public User GetUserWithCompanies(string userName)
{
// query code here
}
}
So now what happens if you need users and say their contact data in one query. Now you have to add another method to your user repository. Now say you need to do another query that also returns the number of clients each company has, so you need to add yet another method (or add an optional parameter). Now say you want to add a query that returns all companies and what users they contain. Now you need a new query method but then comes the question of do you put that in the User repository or the Company repository? How do you keep track of which one it's in and make it simple to choose between GetUserWithCompany and GetCompanyWithUsers when you need it later?
Everything gets very complex from that point on, and it's those situations that have made me drop the repository pattern. What I do now for data access is I create individual query and command classes, each class represents 1 (and only 1) query or data update command to the database. Each query class returns a view model that only contains the data I need for one specific user usage scenario. There are other data access patterns that will work too (specification pattern, some good devs even say you should just do your data access in your controllers since EF is your data access layer).
The key to doing data access successfully is good planning. Do you know what your screens are going to look like? Do you know how users are going to use your system? Do you know all the data that is actually going to be on each screen? If the answer to any of these is no, then you need to take a step back and forget about the data layer, because the data layer is (or should be for a good application) determined based on how the application is actually going to be used, the UI and the screens should not be dependent on how the data layer was designed. If you don't take your UI needs and user usage scenarios into account when developing the data access, your application will not scale well and will not be performant. Sometimes that's not an issue if you don't plan on your site being big, but it never hurts to keep those things in mind.
No matter what you do, you may consider moving instantiation and disposing of your context to your controller like this:
public class MyController : Controller
{
private Entities context = new Entities();
...
public override void Dispose()
{
context.Dispose();
}
}
You can then pass that context into any method that needs it without duplicating the overhead of creating it.
I disagree that the repository pattern is necessarily bad for the same reason. You create multiple classes to break up your code to make it manageable and still reuse the same context. That could look something like this:
repository.Users.GetUser(userName);
In this case "Users" is a lazy loaded instance of your user repository class which reuses the context from your repository. So the code for that Users property in your repository would look something like this:
private UserRepository users;
public UserRepository Users
{
get
{
If (users == null)
{
users = new UserRepository(this);
}
return users;
}
}
You can then expose your context to these other lazy loaded classes via a property.
I don't think this necessarily conflicts with KallDrexx's pattern. His method simply flips this so instead of
repository.Users.GetUser(userName);
You would have something like
UserQuery query = new UserQuery(repository.Users);
This then becomes an issue of syntax. Do you want this:
repository.Area.Query(value1, value2, ...);
Or this:
AreaQuery query = new AreaQuery { Property1 = value1, ... };
The latter actually works nicer with model binding but obviously is more verbose when you actually have to code it.
Best advice KallDrexx gave is to just put your code I your actions and then figure it out. If you are doing simple CRUD, then let MVC instantiate and populate your model, then all you have to do is attach and save. If you find you can reuse code, move it to where it can be reused. If your application starts getting too complicated, try some of these recommendations until you find what works for you.

wcf and Validation Application Block unit testing

I'm trying to test validation that I've setup for my wcf service. What's the best way to do it?
[ServiceContract]
[ValidationBehavior]
public interface IXmlSchemaService
{
[OperationContract(Action = "SubmitSchema")]
[return: MessageParameter(Name = "SubmitSchemaReturn")]
[FaultContract(typeof(ValidationFault))]
JobData SubmitSchema([XmlStringValidator] string xmlString);
}
XmlStringValidator is a custom validator I've created. Ideally I want something like:
XmlSchemaService service = new XmlSchemaService();
service.SubmitSchema();
But in this case, validation isn't called.
By definition, this sort of test is an integration test, not a unit test. The VAB validation will only take place if the service operation is invoked via the WCF pipeline.
While you could perhaps force your calls through the WCF pipeline without creating a client proxy, wouldn't it make more sense to test this from a client proxy in order to ensure that the client is seeing exactly the fault you wish to publish from your service when the validation fails?
You can test out the validation in isolation. While it is not feasible to have validation invoked when running the service code directly, the Validation Application Block has two methods for testing your code (that I am aware of).
Using the ValidatorFactory to create a validator for your input type and Assert that the validation results contain the expected errors.
Instantiating the Validator directly and testing it with various input.
In practice I end up using a combination of the two techniques. I use method one to test for validation errors on complex input types. As an example:
[DataContract]
public class Product
{
[DataMember, NotNullValidator]
public string Name { get; set; }
[DataMember, RangeValidator(0.0, RangeBoundaryType.Exclusive,
double.MaxValue, RangeBoundaryType.Ignore,
ErrorMessage = "The value cannot be less than 0.")]
public double Price { get; set; }
}
[TestMethod]
public void InvalidProduct_ReturnsValidationErrors()
{
Product request = new Product()
{
Price = -10.0
};
var validatorFactory = EnterpriseLibraryContainer.Current
.GetInstance<ValidatorFactory>();
var validator = validatorFactory.CreateValidator<Product>();
var results = validator.Validate(request);
Assert.IsTrue(results.Any(vr => vr.Key == "Name"
&& vr.Message == "The value cannot be null."));
Assert.IsTrue(results.Any(vr => vr.Key == "Price"
&& vr.Message == "The value cannot be less than 0."));
}
For method 2 I would have tests that cover my use case scenarios for Validators I've created. As another example:
[TestMethod]
public void XmlStringValidator_ReturnsErrors_OnInvalidInput()
{
var validator = new XmlStringValidator();
var results = validator.Validate("Your input goes here");
Assert.IsTrue(results.Any(vr => vr.Key == "[KeyNameInValidator]" &&
vr.Message == "[Expected error message based on input]"));
}
Method 2 will allow you to create as many test scenarios as you would like for your XmlStringValidator.
You can find more information about these methods in this article: Chapter 6 - Banishing Validation Complication