Я медленно начинаю развязывать модульное тестирование и насмешливость, но это медленный процесс. Я попробовал модульное тестирование этого кода Active Directory. Вопрос не имеет строгого отношения к AD.Слишком много интерфейсов и оберток?
class ActiveDirectoryQueryer {
DirectorySearcher mSearcher;
public ActiveDirectoryQueryer() {
var searcher = new DirectorySearcher(...);
}
public void GetAllMailEntries() {
MailEntries =
mSearcher
.FindAll()
.Select(result => result.GetDirectoryEntry())
.Select(BuildNewADUser)
.ToList();
}
static ActiveDirectoryUser BuildNewADUser(DirectoryEntry pDirectoryEntry) {
return ActiveDirectoryUser.Create(
pDirectoryEntry.Guid,
(pDirectoryEntry.Properties["name"].Value ?? "").ToString(),
(pDirectoryEntry.Properties["mail"].Value ?? "").ToString()
);
}
Итак, я хотел бы модульное тестирование методы GetAllMailEntries
. Чтобы сделать это с помощью MOQ, мне пришлось вручную создавать интерфейсы и обертки для различных типов .NET и вместо этого менять многие из приведенных выше ссылок на интерфейсы (например, IDirectoryEntry
). Каждый из интерфейсов IXxxx
имеет соответствующий класс-оболочку XxxxWrapper
. Всего я добавил не менее 12 новых исходных файлов только для этого теста. Вот что я получил для модульного теста:
[TestMethod]
public void TestGetAllMailEntries() {
var mockSearcher = new Mock<IDirectorySearcher>();
var mockResultCollection = new Mock<ISearchResultCollection>();
var mockSearchResult = new Mock<ISearchResult>();
var mockDirectoryEntry = new Mock<IDirectoryEntry>();
var mockPropertyCollection = new Mock<IPropertyCollection>();
var nameMockPropertyValueCollection = new Mock<IPropertyValueCollection>();
var mailMockPropertyValueCollection = new Mock<IPropertyValueCollection>();
const string name = "SomeNameValue";
const string mailAddress = "SomeMailAddress";
nameMockPropertyValueCollection.SetupGet(pvc => pvc.Value).Returns(name);
mailMockPropertyValueCollection.SetupGet(pvc => pvc.Value).Returns(mailAddress);
mockPropertyCollection.SetupGet(pc => pc["name"]).Returns(nameMockPropertyValueCollection.Object);
mockPropertyCollection.SetupGet(pc => pc["mail"]).Returns(mailMockPropertyValueCollection.Object);
mockDirectoryEntry.SetupGet(de => de.Properties).Returns(mockPropertyCollection.Object);
mockSearchResult.Setup(sr => sr.GetDirectoryEntry()).Returns(mockDirectoryEntry.Object);
mockResultCollection.Setup(results => results.GetEnumerator()).Returns(new List<ISearchResult> { mockSearchResult.Object }.GetEnumerator());
mockSearcher.Setup(searcher => searcher.FindAll()).Returns(mockResultCollection.Object);
var queryer = new ActiveDirectoryQueryer(mockSearcher.Object);
queryer.GetAllMailEntries();
Assert.AreEqual(1, queryer.MailEntries.Count());
var entry = queryer.MailEntries.Single();
Assert.AreEqual(name, entry.Name);
Assert.AreEqual(mailAddress, entry.EmailAddress);
}
Нормально ли иметь это много интерфейсов и классов-оболочек? (Обертки необходимы, так как типы .NET не могут иначе реализовать мои интерфейсы.)
Я кратко рассмотрел вашу установку и последующее поражает меня очень быстро. Вместо статической функции «BuildNewADUser». Поместите это в новый сервис (интерфейс) и дайте ему именно то, что ему нужно. Например, IActiveDirectoryUserFactory.Create (Guid id, имя строки, строковое письмо) возвращает ActiveDirectoryUser. Теперь вы можете MUCH легче тестировать свой начальный класс, только имея в виду один интерфейс, и это один из методов. –
@Atoms Спасибо, мне нравится эта идея несколько, но я не вижу, как это позволит мне не издеваться над «DirectorySearcher». –