Hello,
I have relatively simple ActorComponent
class that registers itself with a mult-cast delegate on a GameInstanceSubsystem
in its BeginPlay
member function.
I am trying to write a small unit test to ensure the correct behaviour, however I am finding it really difficult to get a World
and GameInstance
setup and running in my test such that the Actor’s lifecycle methods are called when it is spawned.
I have simplified the issue down to just an Actor in order to raise this question. With the code outlined below, it all works as expected when setup in the editor, however the the test fails because the the Actor’s BeginPlay member function is never called, so it never registers itself as a delegate.
Please could someone advise on what else needs to be set up in the test for the BeginPlay
member to be called?
I know I could do this in a Automated Functional test, however that seems like quite a lot of overhead for such seemingly simple simple test. Plus, I’d ideally prefer to keep everything in code where I can.
SomeSubsystem.h:
#pragma once
#include "CoreMinimal.h"
#include "SomeSubsystem.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FComponentsDelegate, int, Value);
UCLASS()
class TESTINGPROJECT_API USomeSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintCallable)
FComponentsDelegate ComponentsDelegate;
};
SomeActor.h
#pragma once
#include "CoreMinimal.h"
#include "SomeActor.generated.h"
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class TESTINGPROJECT_API ASomeActor : public AActor
{
GENERATED_BODY()
public:
int GetCount() const { return Count; }
protected:
virtual void BeginPlay() override;
private:
UFUNCTION()
void BumpCount(int Increase);
UPROPERTY(VisibleAnywhere)
int Count = 0;
};
SomeActor.cpp
#include "SomeActor.h"
#include "SomeSubsystem.h"
void ASomeActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Log, TEXT("Registered with Some Subsystem"))
GetWorld()->GetGameInstance()->GetSubsystem<USomeSubsystem>()->ComponentsDelegate.AddDynamic(this, &ASomeActor::BumpCount);
UE_LOG(LogTemp, Log, TEXT("Registered with Some Subsystem"))
}
void ASomeActor::BumpCount(int Increase)
{
UE_LOG(LogTemp, Log, TEXT("Updating count"))
Count += Increase;
}
SomeActorTest.cpp
#include "Misc/AutomationTest.h"
#include "TestingProject/SomeActor.h"
#include "TestingProject/SomeSubsystem.h"
#include "Tests/AutomationEditorCommon.h"
IMPLEMENT_SIMPLE_AUTOMATION_TEST(SomeActorTest, "Test.SomeComponentUpdateTest",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
bool SomeActorTest::RunTest(const FString& Parameters)
{
UGameInstance *GameInstance = NewObject<UGameInstance>();
GameInstance->Init();
UWorld *World = FAutomationEditorCommonUtils::CreateNewMap();
World->SetGameInstance(GameInstance);
const ASomeActor *Actor = World->SpawnActor<ASomeActor>();
TestEqual("Actor starts with count of 0", Actor->GetCount(), 0);
World->GetGameInstance()->GetSubsystem<USomeSubsystem>()->ComponentsDelegate.Broadcast(20);
TestEqual("Actor increase count by 20 after subsystem broadcasts", Actor->GetCount(), 20);
return true;
}