# cria-usuario-unico.Tests.ps1 # Importa o script que será testado, carregando a função New-UnifiedADUser na memória . "$PSScriptRoot\cria-usuario-unico.ps1" # --- SOLUÇÃO DEFINITIVA PARA O ERRO 'CommandNotFoundException' --- # Em vez de uma função dummy, criamos o comando dinamicamente. # Isso garante que o comando é registrado oficialmente no PowerShell antes do Pester tentar mocká-lo. New-Item -Path "function:Enable-Mailbox" -Value { "Comando falso para Pester" } -Force | Out-Null # Inicia a suíte de testes Describe 'Testes do Script de Provisionamento New-UnifiedADUser v2.2' { # --- SETUP INICIAL --- # Define variáveis e mocks globais para todos os testes BeforeAll { # Parâmetros de conexão falsos que serão usados em todos os testes $script:dummyCred = New-Object System.Management.Automation.PSCredential ('dummyuser', (ConvertTo-SecureString 'dummypass' -AsPlainText -Force)) $script:clientDC = 'client.dc.local' $script:exchangeDC = 'exchange.dc.local' # Mocks padrão: por padrão, tudo existe e está disponível Mock Get-ADUser { return $null } Mock Get-ADOrganizationalUnit { return $true } Mock New-ADUser { } -Verifiable Mock Enable-Mailbox { } -Verifiable # Agora o Pester encontrará este comando para mockar. Mock Get-ADForest { return [PSCustomObject]@{ UPNSuffixes = @('cliente.com.br', 'legacy.local') RootDomain = 'cliente.com.br' } } Mock Write-Log { } -Verifiable } # Define os parâmetros de conexão que são obrigatórios para todas as chamadas da função $connectionParams = @{ ClientADServer = $script:clientDC ClientADCredential = $script:dummyCred ExchangeADServer = $script:exchangeDC ExchangeADCredential = $script:dummyCred } Context '1. Validação de Parâmetros Essenciais' { It '1.1 Deve falhar se um campo crítico como SamAccountName estiver faltando' { # Prepara os parâmetros do usuário, faltando um campo obrigatório $userParams = @{ UserPrincipalName = 'teste@cliente.com.br' GivenName = 'Teste' Surname = 'Sobrenome' Name = 'Nome Completo' Path = 'OU=Teste,DC=local' } # Executa a função com os parâmetros de conexão e do usuário New-UnifiedADUser @connectionParams @userParams # A função New-ADUser NUNCA deve ser chamada Assert-VerifiableMocks { New-ADUser | Should -Not -BeCalled } # O log de erro deve ser chamado com a mensagem correta Assert-VerifiableMocks { Write-Log -Level 'ERROR' -WithMessage "USUÁRIO IGNORADO: O campo crítico 'SamAccountName' está faltando para ''." | Should -BeCalled } } } Context '2. Validação de Pré-Voo (Pre-flight Checks)' { It '2.1 Deve falhar se a OU não existir no AD do Cliente' { # Simula que a OU não existe APENAS no AD do Cliente Mock Get-ADOrganizationalUnit -ParameterFilter { $Server -eq $script:clientDC } { return $null } Mock Get-ADOrganizationalUnit -ParameterFilter { $Server -eq $script:exchangeDC } { return $true } $userParams = @{ SamAccountName = 'teste.ou1'; UserPrincipalName = 'teste.ou1@cliente.com.br'; GivenName = 'T'; Surname = 'O'; Name = 'TO'; Path = 'OU=Inexistente,DC=local' } New-UnifiedADUser @connectionParams @userParams Assert-VerifiableMocks { New-ADUser | Should -Not -BeCalled Write-Log -Level 'ERROR' -WithMessage "USUÁRIO IGNORADO: A OU 'OU=Inexistente,DC=local' não foi encontrada no AD do Cliente." | Should -BeCalled } } It '2.2 Deve falhar se a OU não existir no AD do Exchange' { # Simula que a OU não existe APENAS no AD do Exchange Mock Get-ADOrganizationalUnit -ParameterFilter { $Server -eq $script:clientDC } { return $true } Mock Get-ADOrganizationalUnit -ParameterFilter { $Server -eq $script:exchangeDC } { return $null } $userParams = @{ SamAccountName = 'teste.ou2'; UserPrincipalName = 'teste.ou2@cliente.com.br'; GivenName = 'T'; Surname = 'O'; Name = 'TO'; Path = 'OU=Inexistente,DC=local' } New-UnifiedADUser @connectionParams @userParams Assert-VerifiableMocks { New-ADUser | Should -Not -BeCalled Write-Log -Level 'ERROR' -WithMessage "USUÁRIO IGNORADO: A OU 'OU=Inexistente,DC=local' não foi encontrada no AD do Exchange." | Should -BeCalled } } It '2.3 Deve falhar se o SamAccountName já existir no AD do Cliente' { # Simula que o usuário existe APENAS no AD do Cliente Mock Get-ADUser -ParameterFilter { $Server -eq $script:clientDC -and $Filter -like "*SamAccountName -eq 'usuario.existente'*" } { return $true } $userParams = @{ SamAccountName = 'usuario.existente'; UserPrincipalName = 'novo.upn@cliente.com.br'; GivenName = 'U'; Surname = 'E'; Name = 'UE'; Path = 'OU=Teste,DC=local' } New-UnifiedADUser @connectionParams @userParams Assert-VerifiableMocks { New-ADUser | Should -Not -BeCalled Write-Log -Level 'ERROR' -WithMessage "USUÁRIO IGNORADO: O SamAccountName 'usuario.existente' já existe no AD do Cliente." | Should -BeCalled } } It '2.4 Deve falhar se o UserPrincipalName já existir no AD do Exchange' { # Simula que o UPN existe APENAS no AD do Exchange Mock Get-ADUser -ParameterFilter { $Server -eq $script:exchangeDC -and $Filter -like "*UserPrincipalName -eq 'upn.existente@cliente.com.br'*" } { return $true } $userParams = @{ SamAccountName = 'novo.sam'; UserPrincipalName = 'upn.existente@cliente.com.br'; GivenName = 'U'; Surname = 'E'; Name = 'UE'; Path = 'OU=Teste,DC=local' } New-UnifiedADUser @connectionParams @userParams Assert-VerifiableMocks { New-ADUser | Should -Not -BeCalled Write-Log -Level 'ERROR' -WithMessage "USUÁRIO IGNORADO: O UserPrincipalName 'upn.existente@cliente.com.br' já existe no AD do Exchange." | Should -BeCalled } } It '2.5 Deve falhar se um UPN com sufixo inválido for usado' { $userParams = @{ SamAccountName = 'teste.upn'; UserPrincipalName = 'teste.upn@dominio.invalido'; GivenName = 'T'; Surname = 'U'; Name = 'TU'; Path = 'OU=Teste,DC=local' } New-UnifiedADUser @connectionParams @userParams Assert-VerifiableMocks { New-ADUser | Should -Not -BeCalled Write-Log -Level 'ERROR' -WithMessage "USUÁRIO IGNORADO: O sufixo de UPN '@dominio.invalido' não é válido na floresta do AD do Cliente." | Should -BeCalled } } } Context '3. Sequência de Execução' { It '3.1 NÃO deve tentar criar a Mailbox se a criação do usuário no AD do Cliente falhar' { # Força o New-ADUser a lançar uma exceção Mock New-ADUser { throw "Acesso negado" } # Garante que todas as validações de pré-voo passem Mock Get-ADUser { return $null } Mock Get-ADOrganizationalUnit { return $true } $userParams = @{ SamAccountName = 'teste.falha'; UserPrincipalName = 'teste.falha@cliente.com.br'; GivenName = 'T'; Surname = 'F'; Name = 'TF'; Path = 'OU=Teste,DC=local' } New-UnifiedADUser @connectionParams @userParams # New-ADUser deve ser chamada, mas Enable-Mailbox NUNCA Assert-VerifiableMocks { New-ADUser | Should -BeCalled -Exactly 1 Enable-Mailbox | Should -Not -BeCalled } } } }