A lot of logic, such as pausing the game, expects a player to exist in the game instance, with a valid controller and some other things. The following sets it up so it should work.

auto* GameInstance = NewObject<UGameInstance>(GEngine);
UWorld* World = UWorld::CreateWorld(EWorldType::Game, false);
//This trigges the creation of a game mode which is required for some things
//Set up the world context which is sometimes required to find the player
FWorldContext& Context = GEngine->CreateNewWorldContext(EWorldType::Game);
Context.GameViewport = NewObject<UGameViewportClient>(GEngine);
Context.OwningGameInstance = World->GetGameInstance();
//Setup the viewport which is required for some things as well
TSharedRef<SOverlay> DudOverlay = SNew(SOverlay);
Context.GameViewport->SetViewportOverlayWidget(nullptr, DudOverlay);
//Spawn the player controller and set up things it often requires
auto* PlayerController = World->SpawnActor<APlayerController>();
auto* LP = NewObject<ULocalPlayer>(GEngine, GEngine->LocalPlayerClass);
PlayerController->Player = LP;
GameInstance->AddLocalPlayer(LP, FPlatformUserId());
auto* Pawn = World->SpawnActor<APawn>();

This setup should also allow for UUserWidgets to be addable to the viewport.