How to mock IdentityServerDbContext to add ApplicationUser - unit-testing

I tried following code but it's give exceptions:
var mockIdsDbContext = new Mock<IdentityServerDbContext>();
var applicationUser = new ApplicationUser()
{
Id = Guid.NewGuid().ToString(),
Email = "shashikant0423#gmail.com",
PhoneNumber = "999999999"
};
var usersTestData = new List<ApplicationUser>() { applicationUser };
var users = MockDbSet(usersTestData);
mockIdsDbContext.Setup(x => x.Users).Returns(userManager.Object.Users);
Mock<DbSet<T>> MockDbSet<T>(IEnumerable<T> list) where T : class, new()
{
IQueryable<T> queryableList = list.AsQueryable();
Mock<DbSet<T>> dbSetMock = new Mock<DbSet<T>>();
dbSetMock.As<IQueryable<T>>().Setup(x => x.Provider).Returns(queryableList.Provider);
dbSetMock.As<IQueryable<T>>().Setup(x => x.Expression).Returns(queryableList.Expression);
dbSetMock.As<IQueryable<T>>().Setup(x => x.ElementType).Returns(queryableList.ElementType);
dbSetMock.As<IQueryable<T>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());
//dbSetMock.Setup(x => x.Create()).Returns(new T());
return dbSetMock;
}
but I got error like:
Can not instantiate proxy of class: RenewPlus.IdentityServer.Data.IdentityServerDbContext. Could not find a parameterless constructor

Instead of mocking the rather complex DbContext I'd recommend instead using the Microsoft.EntityFrameworkCore.InMemory driver.
https://learn.microsoft.com/en-us/ef/core/providers/in-memory/

Related

Is it possible to mock the HttpContext for a HubCallerContext?

I am attempting to mock out my SignalR hub for some unit tests. I am running into an issue on my Hubs OnConnectedAsync() call due to using a header to auto join a group if it exists. My issue is lying with the fact that the HubCallerContext.GetHttpContext() method is an extension method and cant be mocked. I dunno if there is a work around to this and I cant seem to find any similarly posted question about this.
OnConnectedAsync() Segment
Context.GetHttpContext().Request.Headers.TryGetValue(SignalRHeaders.GroupHeader, out StringValues header);
if (header.Any())
{
await Groups.AddToGroupAsync(Context.ConnectionId, SignalRConstants.Group);
}
Base Test Class
public DefaultHubBaseTest()
{
var memberId = Guid.NewGuid().ToString();
var orgId = Guid.NewGuid().ToString();
MockClients = new Mock<IHubCallerClients>();
MockClientProxy = new Mock<IClientProxy>();
MockClients.Setup(clients => clients.Group(It.IsAny<string>()))
.Returns(MockClientProxy.Object);
MockGroups = new Mock<IGroupManager>();
MockGroups.Setup(x => x.AddToGroupAsync(It.IsAny<string>(), It.IsAny<string>(), default(CancellationToken))).Returns(Task.CompletedTask);
MockGroups.Setup(x => x.RemoveFromGroupAsync(It.IsAny<string>(), It.IsAny<string>(), default(CancellationToken))).Returns(Task.CompletedTask);
Mock<HttpRequest> MockRequest = new Mock<HttpRequest>();
MockRequest.Setup(x => x.Headers).Returns(new HeaderDictionary()
{
{ SignalRHeaders.GroupHeader, orgId },
{ SignalRHeaders.GroupAdminHeader, "t" },
});
Mock<HttpContext> MockHttpContext = new Mock<HttpContext>();
MockHttpContext.Setup(x => x.Request).Returns(MockRequest.Object);
MockContext = new Mock<HubCallerContext>();
MockContext.Setup(x => x.ConnectionId).Returns("1");
MockContext.Setup(x => x.User.Claims).Returns(new List<Claim>() { new Claim(SignalRConstants.AzureAuthOID, memberId) });
MockContext.Setup(x => x.GetHttpContext()).Returns(MockHttpContext.Object);
DefaultHub = new DefaultHub()
{
Context = MockContext.Object,
Groups = MockGroups.Object,
Clients = MockClients.Object,
};
}
If anyone could help me with this, I would greatly appreciate it. Thanks!

Test Automapper return collection or not

I am testing one of my services - movieService. GetLatestMovies method should return all movies, ordered by date. I am using automapper to map the entity Movie to MovieViewModel.
* Question 1: * How am I supposed to test that, should I set the return collection in the test or what?
* Question 2: * I am filling the InMemory database with a few movies and I am expecting correct ordered result from the movieService, how am I supposed to check, If the service is returning correct result, If I set the return from the automapper?
TestUtils.FillContextWithActorsMoviesAndGenres(options) - just fills the context with a few movies.
This is the movieService method I am testing
public async Task<ICollection<MovieViewModel>> GetLatestMoviesAsync()
{
var movies = await this.context.Movies
.Include(um => um.ApplicationUserMovie)
.ThenInclude(u => u.User)
.Include(x => x.Genre)
.Include(x => x.MovieActor)
.ThenInclude(x => x.Actor)
.OrderByDescending(x => x.CreatedOn).ToListAsync();
var returnMovies = this.mappingProvider.MapTo<ICollection<MovieViewModel>>(movies);
return returnMovies;
}
[TestMethod]
public async Task Return_TwoMoviesWithHighestRating()
{
var dabataseName = nameof(Return_TwoMoviesWithHighestRating);
var options = TestUtils.GetOptions(dabataseName);
// We fill the context with data and save it.
TestUtils.FillContextWithActorsMoviesAndGenres(options);
var movieOne = new MovieViewModel()
{
Name = "BestRatedMovieTest",
Duration = 90,
Director = "TestDirector",
Storyline = "TestStoryline",
ImageUrl = "TestImageUrl",
Genre = "Comedy"
};
var movieTwo = new MovieViewModel()
{
Name = "SecondMovieTestName",
Duration = 90,
Director = "TestDirector",
Storyline = "TestStoryline",
ImageUrl = "TestImageUrl",
Genre = "Comedy"
};
var collectionMovieViewModels = new List<MovieViewModel>() { movieOne, movieTwo };
var mappingProviderMock = new Mock<IMappingProvider>();
mappingProviderMock
.Setup(x => x.MapTo<ICollection<MovieViewModel>>(It.IsAny<List<Movie>>()))
.Returns(collectionMovieViewModels);
using (var actAndAssertContext = new MovieManagementContext(options))
{
var sut = new MovieService(actAndAssertContext, mappingProviderMock.Object);
var movies = await sut.GetLatestMoviesAsync();
Assert.AreEqual(2, movies.Count());
Assert.AreEqual("BestRatedMovieTest", movies.FirstOrDefault().Name);
}
}
I created an empty collection and set the Callback of the method to fill that collection,
var collectionOfMovies = new List<Movie>();
var mappingProviderMock = new Mock<IMappingProvider>();
mappingProviderMock
.Setup(x => x.MapTo<ICollection<MovieViewModel>>(It.IsAny<List<Movie>>()))
.Callback<object>(inputargs => collectionOfMovies = inputargs as List<Movie>);

Unit tests - entity framework

I use NUnitAdapter. I have unit test for my update method:
[Test]
public void UpdateBuisness()
{
var buis = new Buisness()
{
Name = "a",
Id = 4,
Enabled = true
};
_buisnessRepository.Insert(buis);
buis.Name = "b";
_buisnessRepository.Update(buis);
Assert.AreEqual(buis.Name, _buisnesses.Last().Name);
}
Update method:
public void Update(Buisness entity)
{
_context.Entry(entity).State = EntityState.Modified;
}
And I get error:
This is weird, because for my co-workers all works.
My mock:
var mockBuisnessesDbSet = new Mock<DbSet<Buisness>>();
mockBuisnessesDbSet.As<IQueryable<Buisness>>().Setup(m => m.Provider)
.Returns(new TestDbAsyncQueryProvider<Buisness>(_buisnesses.Provider));
mockBuisnessesDbSet.As<IQueryable<Buisness>>().Setup(m => m.Expression).Returns(_buisnesses.Expression);
mockBuisnessesDbSet.As<IQueryable<Buisness>>().Setup(m => m.ElementType).Returns(_buisnesses.ElementType);
mockBuisnessesDbSet.As<IDbAsyncEnumerable<Buisness>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<Buisness>(_buisnesses.GetEnumerator()));
mockBuisnessesDbSet.As<IQueryable<Buisness>>().Setup(m => m.GetEnumerator()).Returns(_buisnesses.GetEnumerator());
mockBuisnessesDbSet.Setup(x => x.Add(It.IsAny<Buisness>()))
.Callback((Buisness bis) => _buisnesses = _buisnesses.Concat(new[] { bis }));
mockBuisnessesDbSet.Setup(x => x.Remove(It.IsAny<Buisness>()))
.Callback((Buisness bis) => _buisnesses = _buisnesses.Where(x => x.Id != bis.Id));
_mockContex = new Mock<ApplicationDbContext>() { CallBase = true };
_mockContex.Setup(x => x.Buisnesses).Returns(mockBuisnessesDbSet.Object);
_buisnessRepository = new BuisnessRepository(_mockContex.Object);
I have no idea what is causing this.

How do I mock the DB models?

I am trying to test a repository and so need to mock the Model Container. Really all I need is to be able to set the Blogs returned to GetBlogs() in the BlogRepository. The repository code is:
private BlogWebsiteModelContainer context;
public BlogRepository(BlogWebsiteModelContainer context)
{
this.context = context;
}
public IEnumerable<Blog> GetBlogs()
{
return context.Blogs;
}
So I want to be able to set what context.Blogs is. I am using Moq and have tried the following:
var mockBlogSet = new Mock<DbSet<Blog>>();
context.Setup(m => m.Blogs).Returns(mockBlogSet.Object);
blogRepo = new BlogRepository(context.Object);
But I get this error message when I debug:
Invalid setup on a non-virtual (overridable in VB) member: m => m.Blogs
Any help greatly appreciated.
Create an interface for your BlogWebsiteModelContainer, then mock the interface. Also instead of defining Blogs on the interface as DbSet<Blog> define it as IQuerayable<Blog>
You can then create a List and use the .AsQueryable extension:
var contextMock = new Mock<IBlogWebsetModelContainer>();
var mockBlogSet = new List<Blog>();
contextMock.Setup(m => m.Blogs).Returns(mockBlogSet.AsQueryable());
blogRepo = new BlogRepository(contextMock.Object);
I found the answer at this link http://msdn.microsoft.com/en-us/data/dn314429.aspx. And so my code became the following:
List<Blog> blogs = new List<Blog>
{
new Blog() { Id = 1 },
new Blog() { Id = 2 },
new Blog() { Id = 3 },
};
var data = blogs.AsQueryable();
var mockSet = new Mock<DbSet<Blog>>();
mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var mockContext = new Mock<BlogWebsiteModelContainer>();
mockContext.Setup(c => c.Blogs).Returns(mockSet.Object);
blogRepo = new BlogRepository(mockContext.Object);
Then I had to go into my BlogWebsiteModelContainer class and change:
public DbSet<Blog> Blogs { get; set; }
to
public virtual DbSet<Blog> Blogs { get; set; }
Just adding the virtual in. And it all worked.
Quick note: reason for creating the list first and then making it .AsQueryable() was so in my code I had the original blog list separate so I could compare it in my tests.

Mock MVC WebViewPage using Moq

I would like to mock a WebViewPage and compare the output with an expected result.
here are my mockhelpers I'm using
public static class MockHelpers
{
public static HttpContextBase MockHttpContext(NameValueCollection queryStringCollection = null)
{
var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
if(queryStringCollection != null)
SetupMockRequestQuerystringValues(request, queryStringCollection);
request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());
var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
response.Setup(x => x.ApplyAppPathModifier(Moq.It.IsAny<String>())).Returns((String url) => url);
// response.SetupGet(x => x.Cookies).Returns(new HttpCookieCollection()); // This also failed to work
var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
context.SetupGet(x => x.Response.Cookies).Returns(new HttpCookieCollection()); // still can't call the Clear() method
context.SetupGet(p => p.User.Identity.Name).Returns("blah");
context.SetupGet(p => p.User.Identity.IsAuthenticated).Returns(true);
return context.Object;
}
private static void SetupMockRequestQuerystringValues( Mock<HttpRequestBase> request, NameValueCollection queryStringCollection)
{
request.SetupGet(x => x.QueryString).Returns(queryStringCollection);
}
public static ViewContext MockViewContext()
{
return CreateSimpleGenericMock<ViewContext>();
}
public static T MockWebViewPage<T>() where T : WebViewPage
{
var mock = new Mock<T>(MockBehavior.Loose) { CallBase = true };
mock.SetupGet(x => x.Context).Returns(MockHttpContext());
mock.SetupGet(x => x.Layout).Returns("layoutName");
mock.SetupGet(x => x.VirtualPath).Returns("virtualPathName");
mock.SetupGet(x => x.Page).Returns(new object{});
mock.SetupGet(x => x.PageData).Returns(new Dictionary<object, dynamic>()
{
{new object(), new object()}
});
var page = mock.Object;
//var helper = new HtmlHelper<object>(new ViewContext { ViewData = CreateSimpleGenericMock<ViewDataDictionary>() }, page, CreateSimpleGenericMock<RouteCollection>());
var helper = new HtmlHelper<object>(new ViewContext { ViewData = new ViewDataDictionary() }, page, new RouteCollection());
page.ViewContext = MockViewContext();
page.Html = helper;
return page;
}
public static T CreateSimpleGenericMock<T>() where T : class
{
var mock = new Mock<T>();
return mock.Object;
}
}
In the MockWebViewPage method you can see all that I have faked. My test method looks like so
[TestMethod]
public void TestMethod1()
{
var coreMasterTestClass = MockHelpers.MockWebViewPage<CoreMaster<object>>();
coreMasterTestClass.ExecutePageHierarchy();
var output = coreMasterTestClass.Html;
}
Is it possible to test the output that will be generated with mocking, and if not does anyone have any possible clues how I could test this. Please note that I'm not testing actual chstml pages but core pages within our own framework.