Mock HttpContext.Current.User.Identity.Name - c#

I'm currently writing unit test for my project where I'm using HttpContext.Current.User.Identity.Name at a defined time. Unfortunately, I can't make the test work since HttpContext is null when I run the test.
I already tried some solution I found on internet like Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("rmllcc"), new string[0]); but I can't get it work.
I'm using a Forms Authenticate system, xUnit with Moq. I'm not testing a controller but a Repository where I'm just logguing each time a user make use of a particular method. How could I accomplish this?

Listen to what your tests are telling you: use the fact that this test is hard to write to think about the structure of your code. You have introduced a dependency in your repository layer to the web application. That's not good. You also have two things going on in your repository: data access and logging.
Maybe wrap the current user in an abstraction that will get the user you need, but can be easily stubbed. Or you could wrap the repository in a decorator that does the logging for you.
Sorry this is not a direct answer to the question but, when tests are hard to write, there is usually a deeper underlying reason that you need to address.

I suggest you dont use the HttpContext from the repository, Make a own context class or a Interface wrapping the user-property.
Something like this:
public class MyContext
{
public MyContext(string username)
{
Username = username;
}
public string Username { get; private set; }
public static MyContext CreateFromHttpContext(HttpContext httpContext){
return new MyContext(HttpContext.Current.User.Identity.Name);
}
}
public class MyRep
{
private readonly VtContext _context;
public MyRep(MyContext context)
{
_context = context;
}
... other repository code...
}
then just create a MyContext in your test:
var rep = new MyRep(new MyContext("unittest"));

Related

unit test for a method that takes an instance through Resolve<T> of Autofac

I'm facing a problem trying to implement a unit test for a method on a service.
The architecture of the project is a little bit cumbersome, to say the less...
The problem is that within the method to test it calls another method to take an instance of another service, here is the little monster:
public void SendOrderEmail(string orderCode)
{
Order order= GetOrderService().SerachByCode(orderCode);
.... Send email with the order ....
}
private IOrderService GetOrderService()
{
return OrderService = AutofacDependencyResolver.Current.ApplicationContainer.Resolve<IOrderService>();
}
Please, don't ask why a service calls another service or why is that service not injected at the constructor, as i said the architecture of this project is weird in some points.
I just need to know what is the way to implement a unit test for a method like that.
Thank you!
I would refactor a little the code, let the class that implement this method have IOrderService injected through the constructor, save the instance and then use it,
this way you can inject your fake IOrderService during the test (or use Automock) :)
If you really really can't change the constructor, you can use a property to set IOrderService
---------------- edit
Since i got some downvote on this answer I've tried to get to understand better what is going on.
I'm not sure about this, but seems like you can't edit this class you wrote about, you just want to test it.
Well if that is the case i think i can still give you some advices.
Advice number one: make a test project, link the class file, make a new file with a class like the following one.
class AutofacDependencyResolver {
public static Current { get; private set; }
public ILifetimeScope ApplicationContainer { get; private set; }
public AutofacDependencyResolver(ILifetimeScope scope) {
Current = this;
ApplicationContainer = scope;
}
}
Since the class you need to test is linked it's gonne to compile it and you just can now achieve what you need.
The other (and i think better) advice is do not test stuff you did not wrote / can't modify. What i'm suggesting is writing an adapter, so a class that use the one you can't modify as a black box.
In this case i think you need to test the email, so just check the email output the address stuff like that and ignore the rest.
the people who wrote those classes should have followed solid principles...
As others have said, and you're probably aware yourself anyway, you really want to refactor classes like this and use constructor injection if at all possible. Service location is generally considered an anti-pattern (https://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/) and it specifically makes unit testing like this harder and less transparent.
However, if you absolutely can't refactor, you can still make methods like this somewhat testable by just providing different registrations for the services you're accessing via service location.
In your case, if you have:
public class EmailSender
{
public void SendOrderEmail(string orderCode)
{
Order order = GetOrderService().SearchByCode(orderCode);
//....Send email with the order ....
}
private IOrderService GetOrderService()
{
return AutofacDependencyResolver.Current.ApplicationContainer.Resolve<IOrderService>();
}
}
...and you're looking to specifically run unit tests over SendOrderEmail to validate the logic surrounding your IOrderService implementation (which could be easily covered by a separate test), the other classes implied there might look like:
public class AutofacDependencyResolver // this is problematic but we can't change it
{
public AutofacDependencyResolver(IContainer applicationContainer)
{
ApplicationContainer = applicationContainer;
}
public IContainer ApplicationContainer { get; }
public static AutofacDependencyResolver Current { get; private set; }
public static void SetContainer(IContainer container)
{
Current = new AutofacDependencyResolver(container);
}
}
public static class ContainerProvider // this sets up production config across your app
{
public static IContainer GetProductionContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<RealOrderService>()
.As<IOrderService>();
// register all other real dependencies here
return builder.Build();
}
}
With that setup, you only need to provide mocks which are required for the specific method you're testing, assuming you can set your container within AutofacDependencyResolver easily in order to have production and test configuration running in parallel. That might look like the following, using xUnit, Moq and Autofac in a test project:
public class EmailSenderTests
{
private readonly Mock<IOrderService> _orderService;
public EmailSenderTests()
{
// to set up the test fixture we'll create a mock OrderService and store a reference to the mock itself for validation later on
_orderService = new Mock<IOrderService>();
var mockOrder = new Order();
_orderService.Setup(os => os.SearchByCode(It.IsAny<string>()))
.Returns(mockOrder);
}
private IContainer GetTestContainer()
{
// here we're adding just one registration we need, setting the mocked OrderService instance to be used for IOrderService
var builder = new ContainerBuilder();
builder.Register(c => _orderService.Object)
.As<IOrderService>();
return builder.Build();
}
[Fact]
public void SendEmail()
{
AutofacDependencyResolver.SetContainer(GetTestContainer()); // set the test container on the global singleton
var sender = new EmailSender();
sender.SendOrderEmail("abc"); // internally the email sender will retrieve the mock IOrderService via service location
// make any assertions here, e.g.
_orderService.Verify(os=>os.SearchByCode("abc"), Times.Exactly(1));
}
}

Unit Test with Effort EF6 with Async Methods

I'm trying to setup Unit tests for this. But every example I've seen that actually works is this type of setup. It will work this way.
//Setup DBContext
public MyContext(DbConnection connection) : base(connection, true){}
//Have some service that gets passed the context etc..
public class SomeService()
{
public SomeService(MyContext passedContext){
Context = passedContext;
}
public MyContext Context {get;set;}
public Book GetBook(int id){
return Context.Books.Find(id);
}
}
But the way I have mine setup is something like this, And I can't figure out how to do it correctly without breaking everything
public class SomeService()
{
public async Task<Book> GetBook(int id){
using(var context = new MyContext()
{
return await context.FindAsync(id);
}
}
}
So how can I test this out, without having a Context Property and passing the context around. Because from what I've read I cant do it async, because DBContext isn't thread safe. But I also cant test it with Effort unless I pass everything the correct context from Effort..
Wont work because I use a using on every service method.
Asyns is not a problem here. Please refer to this question to see how implement factory method:
What happens to using statement when I move to dependency injection

How to prevent database effect in C# MVC Unit testing?

when I applying the unit testing on Insert, Update and Delete operation. At that time the record inserted, updated and deleted in the database as well.
How it possible?
Can anyone give the solution to prevent the database effect?
Thanks,
Ideally you should be using mocking for scenarios where db interaction is there. Make sure you have separate out your db interaction logic and it is interface driven. Then you can create mock objects, wherein you define the expectation of your db interaction interfaces. So for example, if for example InsertSomething() method is called, what should be returned from this method? and so on. Sharing some links on details about unit testing and mocking.
https://msdn.microsoft.com/en-us/library/ff650441.aspx
https://github.com/Moq/moq4
http://www.developerhandbook.com/unit-testing/writing-unit-tests-with-nunit-and-moq/
Testing a MVC Controller fails with NULL reference exception
As another option, you can go for separate real database for testing purpose, if it is essential to execute tests against database. You can also, execute sql script at the start and after running the test to seed and clean data respectively to keep the database pristine
It is possible either by mocking your database (used in unit tests) or creating new database used only for testing purpose (integration tests).
I would recommend using these two approaches together. Remember, that amount of unit tests should be much bigger than integration tests.
Here is simple example how to mock database (using Moq library).
public class HomeController : Controller
{
private IUserRepository _repository;
public HomeController(IUserRepository repository)
{
_repository = repository;
}
public ActionResult AddNewUser(User newUser)
{
_repository.AddUser(newUser);
return View();
}
}
public interface IUserRepository
{
void AddUser(User newUser);
}
public class UserRepository : IUserRepository
{
private DBContext _context;
public UserRepository(DBContext context)
{
_context = context;
}
public void AddUser(User newUser)
{
_context.Users.Add(newUser);
}
}
[Test]
public void ShouldMockRepository()
{
// Given
var repository = new Mock<IUserRepository>();
var controller = new HomeController(repository.Object);
// When
controller.AddNewUser(new User());
// Then
repository.Verify(r => r.AddUser(It.IsAny<User>()), Times.Once);
}

mvc5: Cannot access a disposed object. asp.net mvc5 using unity

im using vs 2013, mvc5 and ef6 + unity.mvc5:
my account controller class has this constructor:
public AccountController(UserManager<ApplicationUser> userManager)
{
this.UserManager = userManager;
}
and this is my unity config:
container.RegisterType(typeof(AccountController),
new InjectionConstructor(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>())));
when i try to register a new user i get this exception:
Cannot access a disposed object.
Object name: 'UserManager`1'.
on this line of code and register action:
var result = await UserManager.CreateAsync(user, model.Password);
when i remove unity and set dependecy resolver to default it works just fine.
i`v tried many unity configs but didnt work...
thanks alot for reading.
i found the solution, changed the unity config to this:
container.RegisterType<IUserStore<ApplicationUser>,
UserStore<ApplicationUser>>(new InjectionConstructor(new ApplicationDbContext()));
thanks all.
Do NOT create a parameterless constructor, (I can't vote it down as I don't have enough reputation), that answer totally avoids IoC and instead tries to build up the object by knowing the entire dependency hierarchy for the object, i.e. AccountController needs to know that it has a dependency on UserStore and it needs to know that Userstore has a dependency on UserContext. This is exactly what DI containers are there to avoid!
It is hard to provide you with an exact answer as there is a lot of your code missing.
One thing that looks odd to me is that you have an uppercase UserManger, that usually means that you are using it as a type, not referencing a local private variable. Can you show me the rest of the code?
Also, I would question why you are not referencing everything via Interfaces. That is by far the preferred way to set up proper DI.
I will try to knock up some test code that shows what I would do and then post this here, if you could answer those questions in the meantime that would be great.
Cheers Mike
Here is what I would do.
In your controller
public class HomeController : Controller
{
private IUserManager<ApplicationUser> userManager;
public HomeController(IUserManager<ApplicationUser> userManager)
{
this.userManager = userManager;
}
public ActionResult Index()
{
var user = "user";
var password = "password";
var result = userManager.CreateAsync(user, password);
return View();
}
}
Interface for UserManager
public interface IUserManager<T> where T : ApplicationUser
{
int CreateAsync(string user, string password);
}
Actual UserManager class
public class UserManager<T> : IUserManager<T> where T : ApplicationUser
{
private IUserStore<ApplicationUser> userStore;
public UserManager(IUserStore<ApplicationUser> userStore)
{
this.userStore = userStore;
}
public int CreateAsync(string user, string password)
{
return 0;
}
}
Interface for UserStore
public interface IUserStore<T> where T : ApplicationUser
{
}
Actual UserStore
public class UserStore<T> : IUserStore<T> where T : ApplicationUser
{
}
Unity configuration
container.RegisterType(typeof (IUserManager<>), typeof (UserManager<>));
container.RegisterType(typeof (IUserStore<>), typeof (UserStore<>));
Hope this helps.
There is obviously lots that is not the same as your app, i.e. not doing the method call async, not reading the password in from the model, etc. but it should give an idea of how to solve the problem that you outlined.
This solution will give you proper constructor dependency injection, which will allow you to have all of your configuration in one place (i.e. the container config) and it will give you interfaces in your constructors which will make it much easier for you to mock those dependencies in your unit tests.
Cheers Mike

How to test EF Models

I am trying to figure out how to write Entity Framework Code First code via TDD. I am finding it hard since it I do not have a test database as I have had in the past with Ruby On Rails. Probably easier to explain with an example:
Currently I have:
public interface IMyContext
{
IDbSet<UserProfile> Users { get; set; }
}
and
public class UserModel
{
IMyContext myContext;
UserModel(IMyContext myContext)
{
this.myContext = myContext;
}
UserProfile GetUser(int id)
{
return myContext.Users.Where(u => u.id == id);
}
}
I am not sure how to test the UserModel code without a running database. I am aware that I can mock the MyContext - but the code myContext.Users.Where ... may involve complex mocking? Have I structured the code wrong? How can I write tests for models without having a test database? Or should I fake the context?
Thanks!
Break your code down into core components and you will realize that all you need to do is mock the context's Users property. After that, the Where is really just a static method working against an IEnumerable object
var users = myContext.Users;
var returnEnumerable = Enumerable.Where(users, u=>u.id == id);
return returnEnumerable
So, just mock your context in such a way that when .Users is called, it returns an IDbSet<UserProfile> of your making

Categories

Resources