Fair enough :) In any case, the original problem is solved. Thanks for the help!
Actually, I found this post while looking for a solution: https://github.com/bUnit-dev/bUnit/discussions/305 Removing the SetupModule from the Testbase and replacing it with
testContext.JSInterop.Mode = JSRuntimeMode.Loose;
did the trick. I can work with this for now. Though, if you have any concerns with this approach, I would be open to hear them. I gotta admit that I don't fully understand what is going on here.
Hi,
while this worked to resolve the dependency, I encountered the following error when adding a form with a TextObject
Bunit.JSRuntimeUnhandledInvocationException: bUnit's JSInterop has not been configured to handle the call:
Bunit.JSRuntimeUnhandledInvocationException
bUnit's JSInterop has not been configured to handle the call:
InvokeVoidAsync("initialize", Microsoft.AspNetCore.Components.ElementReference, "0HN55GR2KUKHU", null, null)
Configure bUnit's JSInterop to handle the call with following:
SetupVoid("initialize", Microsoft.AspNetCore.Components.ElementReference, "0HN55GR2KUKHU", null, null)
or the following, to match any arguments:
SetupVoid("initialize", _ => true)
The setup methods are available on an instance of the BunitJSInterop or
BunitJSModuleInterop type. The standard BunitJSInterop is available
through the TestContext.JSInterop property, and a BunitJSModuleInterop
instance is returned from calling SetupModule on a BunitJSInterop instance.
at Bunit.BunitJSInterop.TryHandlePlannedInvocation[TValue](JSRuntimeInvocation invocation) in /_/src/bunit.web/JSInterop/BunitJSInterop.cs:line 83
at Bunit.BunitJSInterop.HandleInvocation[TValue](JSRuntimeInvocation invocation) in /_/src/bunit.web/JSInterop/BunitJSInterop.cs:line 68
at Bunit.JSInterop.Implementation.JSRuntimeExtensions.HandleInvokeAsync[TValue](BunitJSInterop jSInterop, String identifier, Object[] args) in /_/src/bunit.web/JSInterop/Implementation/JSRuntimeExtensions.cs:line 9
at Bunit.BunitJSObjectReference.InvokeAsync[TValue](String identifier, Object[] args) in /_/src/bunit.web/JSInterop/Implementation/BunitJSObjectReference.cs:line 26
at Microsoft.JSInterop.JSObjectReferenceExtensions.InvokeVoidAsync(IJSObjectReference jsObjectReference, String identifier, Object[] args)
at Blazorise.Modules.BaseJSModule.InvokeSafeVoidAsync(String identifier, Object[] args)
at Blazorise.TextEdit.OnFirstAfterRenderAsync()
at Blazorise.BaseAfterRenderComponent.OnAfterRenderAsync(Boolean firstRender)
at Blazorise.BaseComponent.OnAfterRenderAsync(Boolean firstRender)
at Bunit.Rendering.TestRenderer.AssertNoUnhandledExceptions() in /_/src/bunit.core/Rendering/TestRenderer.cs:line 625
at Bunit.Rendering.TestRenderer.Render[TResult](RenderFragment renderFragment, Func`2 activator) in /_/src/bunit.core/Rendering/TestRenderer.cs:line 480
at Bunit.Rendering.TestRenderer.RenderFragment(RenderFragment renderFragment) in /_/src/bunit.core/Rendering/TestRenderer.cs:line 101
at Bunit.Extensions.TestContextBaseRenderExtensions.RenderInsideRenderTree(TestContextBase testContext, RenderFragment renderFragment) in /_/src/bunit.core/Extensions/TestContextBaseRenderExtensions.cs:line 43
at Bunit.Extensions.TestContextBaseRenderExtensions.RenderInsideRenderTree[TComponent](TestContextBase testContext, RenderFragment renderFragment) in /_/src/bunit.core/Extensions/TestContextBaseRenderExtensions.cs:line 23
at Bunit.TestContext.Render[TComponent](RenderFragment renderFragment) in /_/src/bunit.web/TestContext.cs:line 68
at Bunit.TestContext.RenderComponent[TComponent](Action`1 parameterBuilder) in /_/src/bunit.web/TestContext.cs:line 54
at BookStore.Blazor.Tests.Index_Tests.Index_Test() in C:\Users\dpichowsky\source\abp\abp-samples\BlazorPageUniTest\test\BookStore.Blazor.Tests\Index_Tests.cs:line 25
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
I fear that this error is thrown because he cannot resolve a dynamically created javascript file. This, of course would make testing difficult while working with Blazorize. Do you have an idea on how to work around this or is this a bUnit issue?
Edit: I pushed the new changes into the repo
hi
Can you fork this sample and add your code to reproduce the error?
Thanks
https://github.com/abpframework/abp-samples/tree/master/BlazorPageUniTest
Hi,
I added my code. It shows the same error as in my project https://github.com/PDarioJer/abp-samples
Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'Volo.Abp.AspNetCore.Components.Web.AbpBlazorMessageLocalizerHelper`1...
Autofac.Core.Registration.ComponentNotRegisteredException
The requested service 'Volo.Abp.AspNetCore.Components.Web.AbpBlazorMessageLocalizerHelper`1[[DummyPlatform.Localization.DummyPlatformResource, DummyPlatform.Domain.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
See https://autofac.rtfd.io/help/service-not-registered for more info.
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType)
at Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetRequiredService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Volo.Abp.AbpTestBaseWithServiceProvider.GetRequiredService[T]()
at DummyPlatform.Blazor.Tests.Items.ItemPage_IntegrationShould.Load_Items() in C:\Users\user\source\repos\DummyPlatform\test\DummyPlatform.Blazor.Tests\Items\ItemPage_IntegrationShould.cs:line 22
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Item.razor
@page "/items"
@using DummyPlatform.Items
@using DummyPlatform.Localization
@using Volo.Abp.AspNetCore.Components.Web
@inherits DummyPlatformComponentBase
@inject IItemAppService ItemAppService
@inject AbpBlazorMessageLocalizerHelper<DummyPlatformResource> LH
<Card>
<CardHeader>
<Row Class="justify-content-between">
<Column ColumnSize="ColumnSize.IsAuto">
<h2>@L["Items"]</h2>
</Column>
</Row>
</CardHeader>
<CardBody>
<DataGrid TItem="ItemDto"
Data="ItemList"
ReadData="OnDataGridReadAsync"
TotalItems="TotalCount"
ShowPager="true"
PageSize="PageSize">
<DataGridColumns>
<DataGridColumn TItem="ItemDto"
Field="@nameof(ItemDto.ItemNr)"
Caption="@L["ItemNr"]"></DataGridColumn>
<DataGridColumn TItem="ItemDto"
Field="@nameof(ItemDto.VariantCode)"
Caption="@L["VariantCode"]"></DataGridColumn>
<DataGridColumn TItem="ItemDto"
Field="@nameof(ItemDto.Description)"
Caption="@L["Description"]"></DataGridColumn>
</DataGridColumns>
</DataGrid>
</CardBody>
</Card>
<Modal @ref="ItemDetailModal">
<_ModalBackdrop></_ModalBackdrop>
<ModalContent IsCentered="true">
<Form>
<ModalHeader>
<ModalTitle>@OpenedItem.ItemNr</ModalTitle>
<CloseButton Clicked="CloseItemDetailModal"></CloseButton>
</ModalHeader>
<ModalBody>
<Field>
<FieldLabel>@L["ItemNr"]</FieldLabel>
<TextEdit @bind-Text="@OpenedItem.ItemNr"></TextEdit>
</Field>
<Field>
<FieldLabel>@L["VariantCode"]</FieldLabel>
<TextEdit @bind-Text="@OpenedItem.ItemNr"></TextEdit>
</Field>
<Field>
<FieldLabel>@L["Description"]</FieldLabel>
<TextEdit @bind-Text="@OpenedItem.Description"></TextEdit>
</Field>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary"
Clicked="CloseItemDetailModal">
@L["Cancel"]
</Button>
</ModalFooter>
</Form>
</ModalContent>
</Modal>
Unit Test
using DummyPlatform.Items;
using DummyPlatform.Localization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using NSubstitute;
using Volo.Abp.AspNetCore.Components.Web;
using Xunit;
namespace DummyPlatform.Blazor.Tests.Items;
public class ItemPage_IntegrationShould : DummyPlatformBlazorTestBase
{
private IItemAppService _itemAppService;
private AbpBlazorMessageLocalizerHelper<DummyPlatformResource> _lh;
[Fact]
public void Load_Items()
{
// Arrange
var ctx = CreateTestContext();
_itemAppService = Substitute.For<IItemAppService>();
_lh = GetRequiredService<AbpBlazorMessageLocalizerHelper<DummyPlatformResource>>();
ctx.Services.AddSingleton(_itemAppService);
ctx.Services.AddSingleton(_lh);
// Act
ctx.RenderComponent<DummyPlatform.Blazor.Pages.Items>();
// Assert
_itemAppService.Received(1).GetListAsync(Arg.Any<GetItemListDto>());
}
}
I kept the Testbase the same as in the blogpost. As you can see, I kept very close to the Tutorial from the ABP documentation, so someone else could encounter the same problem. Do I maybe have a missing dependency here?
Once I updated the nuGet packages to the new ABP version, my integration tests throw the following error. As you can see, I used the SampleTests as an example:
Volo.Abp.AbpInitializationException : An error occurred during the initialize Volo.Abp.Modularity.OnApplicationInitializationModuleLifecycleContributor phase of the module MyProject.MyProjectTestBaseModule, MyProject.TestBase, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: Method not found: 'System.String Volo.Abp.Localization.LanguageInfo.get_FlagIcon()'.. See the inner exception for details. ---- System.MissingMethodException : Method not found: 'System.String Volo.Abp.Localization.LanguageInfo.get_FlagIcon()'.
I have adjusted the LocalizationOptions according to the migration guide and I have also created a new migration and applied it
Full stacktrace:
ModuleManager.InitializeModules(ApplicationInitializationContext context) AbpApplicationBase.InitializeModules() AbpApplicationWithExternalServiceProvider.Initialize(IServiceProvider serviceProvider) AbpIntegratedTest`1.ctor() MyProjectTestBase`1.ctor() MyProjectDomainTestBase`1.ctor() SampleDomainTests`1.ctor() Zeile 20 EfCoreSampleDomainTests.ctor() RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions) ----- Inner Stack Trace ----- LanguageManagementDataSeeder.SeedAsync() AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) LanguageManagementDataSeeder.SeedAsync() LanguageManagementDataSeedContributor.SeedAsync(DataSeedContext context) DataSeeder.SeedAsync(DataSeedContext context) AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo) CastleAbpMethodInvocationAdapter.ProceedAsync() UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed) <<SeedTestData>b__0>d.MoveNext() Zeile 41 --- End of stack trace from previous location --- TaskExtensions.WaitAndUnwrapException(Task task) <>c__DisplayClass15_0.<Run>b__0(Task t) ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) --- End of stack trace from previous location --- TaskExtensions.WaitAndUnwrapException(Task task) AsyncContext.Run(Func`1 action) AsyncHelper.RunSync(Func`1 action) MyProjectTestBaseModule.SeedTestData(ApplicationInitializationContext context) Zeile 37 MyProjectTestBaseModule.OnApplicationInitialization(ApplicationInitializationContext context) Zeile 32 OnApplicationInitializationModuleLifecycleContributor.Initialize(ApplicationInitializationContext context, IAbpModule module) ModuleManager.InitializeModules(ApplicationInitializationContext context)
Hi, we removed the
FlagIcon
property in this version, please see the migration guide. You should probably have an old NuGet package version somewhere in your test application, or in one of the dependent projects. Please check package versions manually. If you could not find the reason, feel free to open a new ticket and after that share your project with us, so we can better assist you.
Thank you. Apparently updating the packages via ABP Suite fixed the versioning problem.
Once I updated the nuGet packages to the new ABP version, my integration tests throw the following error. As you can see, I used the SampleTests as an example:
Volo.Abp.AbpInitializationException : An error occurred during the initialize Volo.Abp.Modularity.OnApplicationInitializationModuleLifecycleContributor phase of the module MyProject.MyProjectTestBaseModule, MyProject.TestBase, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: Method not found: 'System.String Volo.Abp.Localization.LanguageInfo.get_FlagIcon()'.. See the inner exception for details.
---- System.MissingMethodException : Method not found: 'System.String Volo.Abp.Localization.LanguageInfo.get_FlagIcon()'.
I have adjusted the LocalizationOptions according to the migration guide and I have also created a new migration and applied it
Full stacktrace:
ModuleManager.InitializeModules(ApplicationInitializationContext context)
AbpApplicationBase.InitializeModules()
AbpApplicationWithExternalServiceProvider.Initialize(IServiceProvider serviceProvider)
AbpIntegratedTest`1.ctor()
MyProjectTestBase`1.ctor()
MyProjectDomainTestBase`1.ctor()
SampleDomainTests`1.ctor() Zeile 20
EfCoreSampleDomainTests.ctor()
RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
----- Inner Stack Trace -----
LanguageManagementDataSeeder.SeedAsync()
AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
LanguageManagementDataSeeder.SeedAsync()
LanguageManagementDataSeedContributor.SeedAsync(DataSeedContext context)
DataSeeder.SeedAsync(DataSeedContext context)
AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
CastleAbpMethodInvocationAdapter.ProceedAsync()
UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
<<SeedTestData>b__0>d.MoveNext() Zeile 41
--- End of stack trace from previous location ---
TaskExtensions.WaitAndUnwrapException(Task task)
<>c__DisplayClass15_0.<Run>b__0(Task t)
ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
TaskExtensions.WaitAndUnwrapException(Task task)
AsyncContext.Run(Func`1 action)
AsyncHelper.RunSync(Func`1 action)
MyProjectTestBaseModule.SeedTestData(ApplicationInitializationContext context) Zeile 37
MyProjectTestBaseModule.OnApplicationInitialization(ApplicationInitializationContext context) Zeile 32
OnApplicationInitializationModuleLifecycleContributor.Initialize(ApplicationInitializationContext context, IAbpModule module)
ModuleManager.InitializeModules(ApplicationInitializationContext context)
Thank you, this helped!
Unfortunately, the GuidGenerator is a protected property, so I won't be able to set it manually. Getting the ItemManager through DI is an option, however, I don't want it to use the actual ItemRepository but a Substitute, so I can return a fake return value on the FindByItemNrAndVariantAsync(...) method.
My question here is: Is there a way to provide the domain service with an implementation of the GuidGenerator without using the IDomainService interface? Or alternatively, is there a way to get the ItemManager through dependency injection but with a mocked ItemRepository?
When I call GuidGenerator.Create() in my DomainService, that I instantiated in a test, I get a NullReferenceException. I think I could solve this by implementing the IDomainService instead and then mock the IGuidGenerator interface. However, there really is no need to do that here aside from testing concerns.
Do you have any suggestions on how to workaround this issue?
(ItemManager.cs)
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
namespace TestPlatform.Items;
public class ItemManager : DomainService
{
private readonly IItemRepository _itemRepository;
public ItemManager(IItemRepository itemRepository)
{
_itemRepository = itemRepository;
}
public async Task<Item> CreateAsync(
string itemNr,
int variantCode,
string description,
)
{
var existingItem = await _itemRepository.FindByItemNrAndVariantAsync(itemNr, variantCode);
if (existingItem != null)
{
throw new ItemAlreadyExistsException(itemNr, variantCode);
}
var newGuid = GuidGenerator.Create();
return new Item(
newGuid,
itemNr,
variantCode,
description,
);
}
}
(ItemManagerTest.cs)
using System.Threading.Tasks;
using TestPlatform.Items.Shared;
using NSubstitute;
using NSubstitute.ReturnsExtensions;
using Shouldly;
using Xunit;
namespace TestPlatform.Items;
public class ItemManager_CreateAsyncShould
{
private IItemRepository itemRepository = Substitute.For<IItemRepository>();
[Fact]
public async Task Return_Item_If_No_Item_With_Same_ItemNr_Exists()
{
itemRepository.FindByItemNrAndVariantAsync(
ValidItemData.ItemNr,
ValidItemData.VariantCode
).ReturnsNull();
var itemManager = new ItemManager(itemRepository);
var item = await itemManager.CreateAsync(
ValidItemData.ItemNr,
ValidItemData.VariantCode,
ValidItemData.Description,
);
item.ShouldBeOfType<Item>();
item.ShouldNotBeNull();
}
}
Edit: For some reason, markdown removes everything inside the <> arrows. However, the content is not important for the problem at hand anyway.