I fixed the error of Request rate is large from CosmosDB by adding the new ConnectionPolicy() variable:
var client = new DocumentClient(new Uri(endpointUri), primaryKey, new ConnectionPolicy()
{
MaxConnectionLimit = 100,
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
RetryOptions = new RetryOptions() { MaxRetryAttemptsOnThrottledRequests = 3, MaxRetryWaitTimeInSeconds = 60 }
});
But I was wondering how can we do unit test to make sure it is actually working?
I am thinking of mocking the DocumentClient and set it up with heavy load. But I am not sure what the syntax should be like..
Here are the sample unit test code for the happy case:
var mockDocumentQuery = new Mock<IFakeDocumentQuery<BookModel>>();
mockDocumentQuery
.SetupSequence(_ => _.HasMoreResults)
.Returns(true)
.Returns(false);
mockDocumentQuery
.Setup(_ => _.ExecuteNextAsync<BookModel>(It.IsAny<CancellationToken>()))
.ReturnsAsync(response);
var provider = new Mock<IQueryProvider>();
provider
.Setup(_ => _.CreateQuery<BookModel>(It.IsAny<Expression>()))
.Returns(mockDocumentQuery.Object);
mockDocumentQuery.As<IQueryable<BookModel>>().Setup(x => x.Provider).Returns(provider.Object);
mockDocumentQuery.As<IQueryable<BookModel>>().Setup(x => x.Expression).Returns(dataSource.Expression);
mockDocumentQuery.As<IQueryable<BookModel>>().Setup(x => x.ElementType).Returns(dataSource.ElementType);
mockDocumentQuery.As<IQueryable<BookModel>>().Setup(x => x.GetEnumerator()).Returns(() => dataSource.GetEnumerator());
var client = new Mock<IDocumentClient>();
client.Setup(_ => _.CreateDocumentQuery<BookModel>(It.IsAny<Uri>(), It.IsAny<FeedOptions>()))
.Returns(mockDocumentQuery.Object);
In the last line of code, how can I setup the DocumentClient with a heavy load?
Related
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!
In order to create the test harness for the SubmitOrderConsumer, I will have to build a ServiceCollection containing all the depdencies of SubmitOrderConsumer.
Mock<INotifier> mockNotifier = new Mock<INotifier>();
Mock<IStockChecker> mockStockChecker = new Mock<IStockChecker>();
Mock<IFidelityUpdater> mockFidelityUpdater = new Mock<IFidelityUpdater>();
Mock<IPromotionManager> mockPromotionManager = new Mock<IPromotionManager>();
await using var provider = new ServiceCollection()
.AddMassTransitTestHarness(cfg =>
{
cfg.AddConsumer<SubmitOrderConsumer>();
})
.AddSingleton<INotifier>(mockNotifier.Object)
.AddSingleton<IStockChecker>(mockStockChecker.Object)
.AddSingleton<IFidelityUpdater>(mockFidelityUpdater.Object)
.AddSingleton<IPromotionManager>(mockPromotionManager.Object)
..
.BuildServiceProvider(true);ds
var harness = provider.GetRequiredService<ITestHarness>();
...
mockNotifier.Verify(...)
The Moq.Automock library helps me to create the SubmitOrderConsumer and auto-mock all its depdencies so the above codes is reduced to
AutoMocker mocker = new AutoMocker();
await using var provider = new ServiceCollection()
.AddMassTransitTestHarness(cfg =>
{
cfg.AddConsumer<SubmitOrderConsumer>();
})
.AddSingleton(mocker.CreateInstance<SubmitOrderConsumer>())
.BuildServiceProvider(true);
var harness = provider.GetRequiredService<ITestHarness>();
...
mocker.GetMock<INotifier>().Verify(...)
Question:
The class AutoMocker is also a IServiceProvider, so the above codes have 2 IServiceProvider:
the first IServiceProvider is the mocker which can resolve the SubmitOrderConsumer
the second IServiceProvider is the provider which can resolve the ITestHarness
is it possible to create the ITestHarness with my mocker IServiceProvider? something like
ITestHarness harness = new ContainerTestHarness(mocker);
I have below code which navigates from one page to other using Navigation Service in Xamarin forms.
On clicking on Observation button it executes ObservationsCommand as shown below.
public Command ObservationsCommand => new Command(async () => await OnObservationsCommandAsync());
After clicking on Observation button it navigates to next page passing the selected data to the navigation service as shown
private async Task OnObservationsCommandAsync()
{
ObservationDetailsParameter selectedData = new ObservationDetailsParameter
{
Cage = DisplayedCage,
Dossiers = DossierList.SelectedItems
};
await _navigationService.NavigateToAsync<ObservationDetailsViewModel>(selectedData);
}
Below is the code for unit test
[Fact]
public void TestOnObservationsCommandAsync()
{
var mockNavigationService = new Mock<INavigationService>();
var mockCageDetailsService = new MockCageDetailsService();
var mockObservationDetailsService = new MockObservationDetailsService();
var mockSettingsService = new MockSettingsService();
Cage _displayedCage = new Cage { Id = 11 };
Dossier _dossier1 = new Dossier { Id = 841 };
var _dossierList = new SelectableItemCollection<Dossier>
{
_dossier1
};
_dossierList.SelectAll();
var cageObsViewModel = new CageObsViewModel(mockNavigationService.Object, mockCageDetailsService, mockSettingsService);
var mockObservationDetailsParameter = new
Mock<IObservationDetailsParameter>();
mockObservationDetailsParameter.Setup(x =>
x.Cage).Returns(_displayedCage);
mockObservationDetailsParameter.Setup(x => x.Dossiers
).Returns(_dossierList.SelectedItems );
cageObsViewModel.DisplayedCage = mockObservationDetailsParameter .Object .Cage ;
cageObsViewModel.DossierList = _dossierList;
// Act
cageObsViewModel.ObservationsCommand.Execute(null);
mockNavigationService.Verify((s) => s.NavigateToAsync<ObservationDetailsViewModel>(mockObservationDetailsParameter.Object));
}
However after executing this test i get error as 'Expected invocation on the mock at least once, but was never performed.'
Will you please help?
This is an example of a unit test I have to verify navigation after successful login.
[Fact]
public async Task ValidCredentials()
{
//Mock login -> false
var authenticationServiceMock = new Mock<IAuthenticationService>();
authenticationServiceMock
.Setup(s => s.Login(It.IsAny<string>(), It.IsAny<string>()))
.Returns(Task.FromResult(true));
LoginViewModel viewModel = new LoginViewModel(authenticationServiceMock.Object);
await viewModel.InitializeAsync(null);
viewModel.UserName.Value = "johann#mail.com";
viewModel.Password.Value = "1234!Maaaa";
viewModel.LoginCommand.Execute(null);
navigationServiceMock.Verify((s) => s.NavigateToAsync<HomeViewModel>());
}
As I am using AutoFac and my ViewModelBase gets the NavigationService instance by itself this is my test setup:
public LoginViewModelTests()
{
ContainerBuilder builder = new ContainerBuilder();
navigationServiceMock = new Mock<INavigationService>();
navigationServiceMock.SetReturnsDefault<Task>(Task.FromResult(0));
builder.RegisterInstance<INavigationService>(navigationServiceMock.Object);
ViewModelLocator.RegisterDependencies(builder);
}
If it is not clear enough let me know and we can review it to better adapt to your case.
How to mock Url.Action during testing controller action?
I'm trying to unit test my asp.net core controller action.
Logic of action has Url.Action and I need to mock it to complete test but I can't find right solution.
Thank you for your help!
UPDATE
this is my method in controller that I need to test.
public async Task<IActionResult> Index(EmailConfirmationViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.FindByNameAsync(model.Email);
if (user == null) return RedirectToAction("UserNotFound");
if (await _userManager.IsEmailConfirmedAsync(user)) return RedirectToAction("IsAlreadyConfirmed");
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Action("Confirm", "EmailConfirmation", new { userId = user.Id, token }, HttpContext.Request.Scheme);
await _emailService.SendEmailConfirmationTokenAsync(user, callbackUrl);
return RedirectToAction("EmailSent");
}
return View(model);
}
I have problem with mocking this part:
var callbackUrl = Url.Action("Confirm", "EmailConfirmation", new { userId = user.Id, token }, HttpContext.Request.Scheme);
Finally I found solution!
When you are mocking UrlHelper you need to mock only base method Url.Action(UrlActionContext context) because all helper methods actually use it.
var mockUrlHelper = new Mock<IUrlHelper>(MockBehavior.Strict);
mockUrlHelper
.Setup(
x => x.Action(
It.IsAny<UrlActionContext>()
)
)
.Returns("callbackUrl")
.Verifiable();
_controller.Url = mockUrlHelper.Object;
Also! I have problem because of null in HttpContext.Request.Scheme. You need to mock HttpContext
_controller.ControllerContext.HttpContext = new DefaultHttpContext();
I added
var urlHelperMock = new Mock<IUrlHelper>();
urlHelperMock
.Setup(x => x.Action(It.IsAny<UrlActionContext>()))
.Returns((UrlActionContext uac) =>
$"{uac.Controller}/{uac.Action}#{uac.Fragment}?"
+ string.Join("&", new RouteValueDictionary(uac.Values).Select(p => p.Key + "=" + p.Value)));
controller.Url = urlHelperMock.Object;
To my generic Controller setup. Which is a bit roughnready but means I can test any controller logic that generates links.
I'm trying to set up a mock of this interface:
public interface IAuthenticatedRequestService
{
HttpClient CreateHttpClientForJwt(Func<HttpResponseMessage, bool> isUnauthenticated, int timeoutSeconds);
HttpClient CreateHttpClientForAccessToken(Func<HttpResponseMessage, bool> isUnauthenticated, int timeoutSeconds);
}
This is one implementation of the method to setup that is in use and working:
public HttpClient CreateHttpClientForAccessToken(Func<HttpResponseMessage, bool> isUnauthenticated, int timeoutSeconds)
{
var client = Mvx.Resolve<IPlatformOperationProvider>().CreateHttpClient(timeoutSeconds);
return new HttpClient(new AuthenticatedHttpMessageHandler(this, client, AuthenticationUtils.AddAccessTokenToRequest, isUnauthenticated,_loggingService));
}
This is one usage of the implemented method that is working:
var client = service.CreateHttpClientForAccessToken(x => x.StatusCode == HttpStatusCode.Unauthorized, CoreConstants.TimeoutMyDetails);
This is my unit test which sets up the mock:
[Test]
public async void TestIsLoggedInIsTrue()
{
//Arrange
var authenticatedRequestService = new Mock<IAuthenticatedRequestService>();
authenticatedRequestService.Setup(foo => foo.CreateHttpClientForAccessToken((It.IsAny<Func <HttpResponseMessage, bool>>())
, 0
)).Returns(new HttpClient());
var platformOperationProvider = new Mock<IPlatformOperationProvider>();
platformOperationProvider.Setup(foo => foo.CreateHttpClient(1)).Returns(new HttpClient());
Mvx.RegisterSingleton<IPlatformOperationProvider>(platformOperationProvider.Object);
Mvx.RegisterSingleton<IAuthenticatedRequestService>(authenticatedRequestService.Object);
var loggedInProvider = new LoggedInProvider(
new Mock<ISecuredSettings>().Object,
new Mock<ILoggingService>().Object
);
//Act
await loggedInProvider.SetUserAndToken(
new User(),
new ApiAccessInfo("refresh token", "access token", "jwt")
);
//Assert
Assert.IsTrue(loggedInProvider.IsLoggedIn);
}
This unit test has no errors, but the test fails (I think it is because I am passing it any HttpResponseMessage? And I need to somehow pass it HttpStatusCode.Accepted? How would I do that?
Take note of the usage of the method, how it passes HttpStatusCode.Unauthorized, then can I do something like that with HttpStatusCode.Accepted?:
var client = service.CreateHttpClientForAccessToken(x => x.StatusCode == HttpStatusCode.Unauthorized, CoreConstants.TimeoutMyDetails);
EDIT: To be clear, It is this line of code that I need to correct:
authenticatedRequestService.Setup(foo => foo.CreateHttpClientForAccessToken((It.IsAny<Func <HttpResponseMessage, bool>>())
, 0
)).Returns(new HttpClient());
EDIT: Whilst debugging the problem starts here (check the code comment after the client is created):
async Task<ServiceResponse> UpdateUserDetails()
{
// Have to late-resolve this otherwise we end up with a dependency loop
var service = Mvx.Resolve<IAuthenticatedRequestService>();
try
{
var client = service.CreateHttpClientForAccessToken(x => x.StatusCode == HttpStatusCode.Unauthorized, CoreConstants.TimeoutMyDetails);
// here is the problem, the client is null after this line of code.
var user = _user;
I have since found that it is not a Moq issue. MvvmCross is not registering the object to resolve correctly.
This line is not working:
Mvx.RegisterSingleton<IAuthenticatedRequestService>(authenticatedRequestService.Object);
as this line creates an AuthenticatedRequestService but it is not the mock one that I made:
var service = Mvx.Resolve<IAuthenticatedRequestService>();
Here is some context of resolving the AuthenticatedRequestService
async Task<ServiceResponse> UpdateUserDetails()
{
// Have to late-resolve this otherwise we end up with a dependency loop
var service = Mvx.Resolve<IAuthenticatedRequestService>();
try
{
var client = service.CreateHttpClientForAccessToken(x => x.StatusCode == HttpStatusCode.Unauthorized, CoreConstants.TimeoutMyDetails);
var user = _user;
var str = await client.GetStringAsync(new Uri(user.IdUrl));
var newUser = JsonConvert.DeserializeObject<User.Json>(str);
var token = _token;
if (token != null)