我最近在Active Directory角色提供程序中重构了一些代码,以删除对多个域的支持。在这个过程中,我的集成测试以我没想到的方式打破了。除非我在测试设置代码和调用被测试方法的代码之间存在显着延迟,否则测试不会可靠地成功。如果我使用调试器运行测试它总是成功,我看不到代码的任何问题。如果我使用自动化工具运行测试,则一个或多个测试失败并以意外的方式失败。
如何可靠地测试使用System.Directory.AccountManagement命名空间类和方法的角色提供程序代码?
注意:为了与SO范例保持一致,我提供的解决方案是我找到的单独答案。但是,如果您认为您的解决方案比我的解决方案更好,我会对其他解决方案持开放态度。这个问题正在提供,因为我找不到任何解决我问题的SO问题。
一些相关问题是:
答案 0 :(得分:0)
我发现问题在于我在角色提供程序中使用的PrincipalSearchers并不总是联系与设置中使用的代码相同的域控制器。这将导致由于域控制器之间的传播延迟而导致的错误。为了解决这个问题,我使用构造函数注入来提供用于设置角色提供程序的PrincipalContext。这允许角色提供程序始终使用与测试代码相同的上下文。此外,我使用基于构造函数注入提供的PrincipalContext的搜索根替换了PrincipalSearcher上的SearchRoot。相关代码如下。请注意,角色提供程序实现IDisposable,以便在外部提供域上下文时处置域上下文。
private bool DisposeContext { get; set; }
private PrincipalContext DomainContext { get; set; }
public PrintAccountingRoleProvider() : this( null ) { }
public PrintAccountingRoleProvider( PrincipalContext domainContext )
{
this.DisposeContext = domainContext == null;
this.DomainContext = domainContext ?? new PrincipalContext( ContextType.Domain );
}
...
private UserPrincipal FindUser( string userName )
{
using (PrincipalSearcher userSearcher = new PrincipalSearcher())
{
UserPrincipal userFilter = new UserPrincipal( this.DomainContext );
userFilter.SamAccountName = userName;
userSearcher.QueryFilter = userFilter;
// Replace the searcher with one directly associated with the context to ensure that any changes
// made elsewhere will be reflected if we call the search immediately following the change. This
// is critical in the integration tests.
var searcher = userSearcher.GetUnderlyingSearcher() as DirectorySearcher;
searcher.SearchRoot = new DirectoryEntry( @"LDAP://" + this.DomainContext.ConnectedServer + @"/dc=iowa,dc=uiowa,dc=edu" );
return userSearcher.FindOne() as UserPrincipal;
}
}
...
private void Dispose( bool disposing )
{
if (!this.disposed)
{
if (disposing)
{
if (this.DisposeContext && this.DomainContext != null)
{
this.DomainContext.Dispose();
this.DomainContext = null;
}
}
this.disposed = true;
}
}