Thank you Enisn, this worked!
Hi,
When I try to execute the following Unit test (please see below) in Volo.Abp.LanguageManagement.Application.Tests (or most of the modules for that matter),
[Fact]
public async Task Get()
{
// Arrange
// Act
var localizedText = await _languageTextAppService.GetAsync("LanguageManagement", "en", "Yes", "en");
//Assert.True(true);
// Assert
localizedText.ShouldNotBeNull();
}
I get an error :
\JetBrains\Installations\ReSharperPlatformVs16_2db4cf06_000\TestRunner\netcoreapp2.0\ReSharperTestRunner.exe:3048 exited with code '-42': Not available
--- EXCEPTION #1/1 [LoggerException] Message = “ Process \JetBrains\Installations\ReSharperPlatformVs16_2db4cf06_000\TestRunner\netcoreapp2.0\ReSharperTestRunner.exe:3048 exited with code '-42': Not available ” ExceptionPath = Root ClassName = JetBrains.Util.LoggerException HResult = COR_E_APPLICATION=80131600
When I debugged the issue further I noticed the error occurs in the following method : (SeedTestData) in the class
namespace Volo.Abp.LanguageManagement
{
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpTestBaseModule),
typeof(AbpAuthorizationModule),
typeof(LanguageManagementDomainModule)
)]
public class LanguageManagementTestBaseModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAlwaysAllowAuthorization();
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("en-US", "en", "English", "flag-icon flag-icon-gb"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe", "flag-icon flag-icon-tr"));
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
SeedTestData(context);
}
private static void SeedTestData(ApplicationInitializationContext context)
{
AsyncHelper.RunSync(async () =>
{
using (var scope = context.ServiceProvider.CreateScope())
{
await scope.ServiceProvider
.GetRequiredService<IDataSeeder>()
.SeedAsync();
}
});
}
}
}
I am unable to debug any further, but I do get to this point and can see the failure happens on SeedAsync(). I think that either the IDataSeeder is not being injected properly, or there is something I need to configure when executing Volo Unit Tests. It is using the in-memory database to seed the data, however I can not get the test to run. The test runner shuts down without any further exception message or stack trace. We have been able to duplicate this on three other developer machines.
Could you pleae provide me with a sample of how to execute the volo test cases in question? Is there something I was supposed to configure? This is specific to the Volo test cases that come out of box, when modules are installed locally using the abp suite tool.
Thanks in advance,
Jesse
Hi Maliming,
I have a method in my razor.cs class :
protected virtual async Task SetPermissionsAsync()
{
HasEditPermission = await AuthorizationService.IsGrantedAsync(UpdatePolicyName);
}
This returns an IAuthorizationService, and comes from the static class AbpAuthorizationServiceExtensions. This method is first Initialized in the following start up method in the razor component:
protected override async Task OnInitializedAsync()
{
await SetPermissionsAsync();
}
This is where the error occurs. I need to pass an instance of the IAuthorizationService to the component during the test. Here is the test I wrote:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Bunit;
using Bunit.TestDoubles;
using Cao.CatOs.Blazor.Pages;
using Cao.CatOs.Blazor.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
using Volo.Abp.Authorization;
using Volo.Abp.LanguageManagement;
using Xunit;
namespace Cao.CatOs.Blazor.Tests
{
public class MultilingualComponent
{
protected string UpdatePolicyName = LanguageManagementPermissions.LanguageTexts.Edit;
[Fact]
public void Should_ReturnMultilingualExportHeader_ForRenderedComponent()
{
// Arrange
using var ctx = new TestContext();
var authContext = ctx.AddTestAuthorization();
authContext.SetAuthorized("admin");
//TODO:Mock parameters for CustomLanguageService using NSubstitute
var languageManagement = Substitute.For<ICustomLanguageTextAppService>();
var navigationManager = Substitute.For<INavigationService>();
var component = Substitute.For<CatOsComponentBase>();
ctx.Services.AddSingleton(component);
ctx.Services.AddSingleton(languageManagement);
ctx.Services.AddSingleton(navigationManager);
// Act
var cut = ctx.RenderComponent<Multilingual>();
// Assert
cut.MarkupMatches("<h3>Multilingual Export</h3>");
}
}
}
The error occurs on the //Act line . The exception is :
Volo.Abp.AbpException
authorizationService should implement Volo.Abp.Authorization.IAbpAuthorizationService
at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.AsAbpAuthorizationService(IAuthorizationService authorizationService)
at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.AuthorizeAsync(IAuthorizationService authorizationService, Object resource, String policyName)
at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.AuthorizeAsync(IAuthorizationService authorizationService, String policyName)
at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.IsGrantedAsync(IAuthorizationService authorizationService, String policyName)
at Cao.CatOs.Blazor.Pages.Multilingual.SetPermissionsAsync() in C:\CAT-OS\src\Cao.CatOs.Blazor\Pages\Multilingual.razor.cs:line 49
at Cao.CatOs.Blazor.Pages.Multilingual.OnInitializedAsync() in C:\CAT-OS\src\Cao.CatOs.Blazor\Pages\Multilingual.razor.cs:line 38
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
at Bunit.Rendering.TestRenderer.AssertNoUnhandledExceptions() in /_/src/bunit.core/Rendering/TestRenderer.cs:line 355
at Bunit.Rendering.TestRenderer.Render[TResult](RenderFragment renderFragment, Func`2 activator) in /_/src/bunit.core/Rendering/TestRenderer.cs:line 237
at Bunit.Rendering.TestRenderer.RenderFragment(RenderFragment renderFragment) in /_/src/bunit.core/Rendering/TestRenderer.cs:line 55
at Bunit.Extensions.TestContextBaseRenderExtensions.RenderInsideRenderTree(TestContextBase testContext, RenderFragment renderFragment) in /_/src/bunit.core/Extensions/TestContextBaseRenderExtensions.cs:line 45
at Bunit.Extensions.TestContextBaseRenderExtensions.RenderInsideRenderTree[TComponent](TestContextBase testContext, RenderFragment renderFragment) in /_/src/bunit.core/Extensions/TestContextBaseRenderExtensions.cs:line 25
at Bunit.TestContext.Render[TComponent](RenderFragment renderFragment) in /_/src/bunit.web/TestContext.cs:line 70
at Bunit.TestContext.RenderComponent[TComponent](ComponentParameter[] parameters) in /_/src/bunit.web/TestContext.cs:line 40
at Cao.CatOs.Blazor.Tests.MultilingualComponent.Should_ReturnMultilingualExportHeader_ForRenderedComponent() in C:\CAT-OS\Cao.CatOs.Blazor.Tests\MultilingualComponent.cs:line 38
The question I have is how do I inject / mock the object Volo.Abp.Authorization.IAbpAuthorizationService, so my test picks it up? Just to be clear I am using BUnit, and my razor component inherits from the AbpComponentBase. This is why when I run the page IABPAuthorizationService exists, however in a unit test it is null.
What I would like is an example of how to take a standard Razor componet that properly implements the ABP framework and write a unit test for it using BUnit. I am sure you will find there are quite a few items that need to be mocked and injected, in order to get it to work properly. Do you have an example I can use to follow along?
Thanks,
Jesse
Hi Enisn,
Further to this question, how can I make the menu items I added invisible when the user is NOT logged in?
Thanks for your help!
Jesse
is it beta version?
Hi Albert,
No it is the commercial version from ABP...
Thanks,
Jesse
Hi Albert,
The ABP Commercial version we are using is Version="4.4.2"
Please let me know if there is anything else you need.
Thanks,
Jesse
Thank you very much Ensin!
Jesse
Thanks Maliming.... I am going to send you a test project shortly with details on what exactly is failing.
Hi,
We are trying to implement a User tracking system inside our application. Basically we want to know who is logged on currently in the site. We have been investigating several ways to do this, and we were going to implement something like the following:
public interface IActiveUserRepository
{
Task AddUserAysnc(UserCircuit user);
Task<IList<UserCircuit>> GetUsers();
}
public class InMemoryActiveUserRepository : IActiveUserRepository
{
private readonly Dictionary<string, UserCircuit> _activeUsers = new();
public Task AddUserAysnc(UserCircuit user)
{
if (!_activeUsers.ContainsKey(user.UserId))
_activeUsers.Add(user.UserId, user);
return Task.CompletedTask;
}
public async Task<IList<UserCircuit>> GetUsers()
{
return await Task.Run(() => _activeUsers.Values.ToList());
}
}
public class CustomAuthStateProvider : AuthenticationStateProvider
{
private readonly IActiveUserRepository _users;
public CustomAuthStateProvider(IActiveUserRepository users)
{
_users = users;
AuthenticationStateChanged += OnAuthenticationStateChanged;
}
private async void OnAuthenticationStateChanged(Task<AuthenticationState> task)
{
var user = (await task).User;
if (user.Identity.IsAuthenticated)
{
await _users.AddUserAysnc(new UserCircuit { UserId = user.Identity.Name });
}
}
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
throw new System.NotImplementedException();
}
}
//public class TrackingCircuitHandler : CircuitHandler
//{
// private readonly HashSet<Circuit> circuits = new();
// public override Task OnConnectionUpAsync(Circuit circuit,
// CancellationToken cancellationToken)
// {
// circuits.Add(circuit);
// return Task.CompletedTask;
// }
// public override Task OnConnectionDownAsync(Circuit circuit,
// CancellationToken cancellationToken)
// {
// circuits.Remove(circuit);
// return Task.CompletedTask;
// }
// public int ConnectedCircuits => circuits.Count;
// public IList<Circuit> ActiveCircuits => circuits.ToList();
//}
public class UserCircuit
{
public string CircuitId { get; set; }
public string UserId { get; set; }
public string Username { get; set; } = "Anonymous";
}
The question I have is , how do I access the AuthenticationStateProvider in ABP Framework? When I try to add the AuthenticationStateProvider via Dependecey Injection, I get an error since it already exists in the container.
Is there something out-of-box implemented by the ABP framework, that I can user to get all currently logged in users of the site? If not how is AuthenticationStateProvider implemented / exposed in the ABP framework?
Any help would be greatly appreciated.
Thanks,
Jesse
Thanks Maliming! This helped alot, and fixed my issues....
Jesse