Могу ли я выполнить модульное тестирование метода, который выполняет контекстные вызовы Sitecore? - PullRequest
4 голосов
/ 12 июля 2010

Я работаю над веб-приложением, созданным на CMS Sitecore.Мне было интересно, можем ли мы выполнить модульное тестирование, например, метод, который берет некоторые данные из Sitecore, выполняет некоторую обработку и выдает результат.Я хотел бы проверить всю логику в методе с помощью юнит-теста.

Я довольно растерялся после поиска в Интернете по всему миру.Некоторые говорят, что этот вид тестирования на самом деле является интеграционным тестированием, а не модульным тестированием, и я должен тестировать только код, который не имеет вызовов Sitecore, другие говорят, что это невозможно, поскольку контекст Sitecore будет отсутствовать.

Iхотел бы попросить вас о помощи у опытных коллег-программистов: могу ли я протестировать метод, содержащий вызовы Sitecore?Если ДА, то как?Если НЕТ, почему?Есть ли обходной путь?

Проект находится в начале, поэтому не будет проблем в выборе между средами модульного тестирования, такими как MSTest или Nunit, если это решение связано с модульным тестированиемрамки выбора.

Ответы [ 5 ]

2 голосов
/ 13 июля 2010

Довольно сложно узнать что-либо о Sitecore без предоставления электронной почты и прохождения рекламной кампании, поэтому я просто предоставлю общий подход к тому, как сделать что-то подобное.

Прежде всего, выПредположим, что API Sitecore гарантированно работает - т.е. это фреймворк - и вы не тестируете модуль it .Вы должны тестировать свои взаимодействия с ним.

Затем загрузите MOQ и прочитайте краткий обзор о том, как его использовать .Это моя любимая насмешливая основа.Не стесняйтесь использовать другие фреймворки, если хотите.

Надеемся, что Sitecore API предоставит вам возможность создавать объекты данных, не имея дело с постоянством, то есть просто создавать новый экземпляр того, что вас интересует.Вот мой воображаемый API:

public class Post {
  public string Body {get;set;}
  public DateTime LastModified {get;set;}
  public string Title {get;set;}
}

public interface ISiteCorePosts {
  public IEnumerable<Post> GetPostsByUser(int userId);
}

В этом случае модульное тестирование должно быть довольно простым.С помощью Dependency Injection вы можете внедрить интерфейсы SiteCore в свой компонент, а затем выполнить его модульное тестирование.

public class MyPostProcessor {

  private readonly ISiteCorePosts m_postRepository;

  public MyPostProcessor(ISiteCorePosts postRepository) {
    m_postRepository = postRepository;
  }

  public void ProcessPosts(int userId) {
     var posts = m_postRepository.GetPostsByUser(userId);
     //do something with posts
  }
}

public class MyPostProcessorTest {
  [TestMethod]
  ProcessPostsShouldCallGetPostsByUser() {
    var siteCorePostsMock = new Mock<ISiteCorePosts>();
    //Sets up the mock to return a list of posts when called with userId = 5
    siteCorePostsMock.Setup(m=>m.GetPostsByUser(5)).Returns(new List<Post>{/*fake posts*/});

    MyPostProcessor target = new MyPostProcessor(siteCorePostsMock.Object);
    target.ProcessPosts(5);
    //Verifies that all setups are called
    siteCorePostsMock.VerifyAll();
  }
}

Если ISiteCorePosts на самом деле не является интерфейсом и представляет собой конкретный класс, методы которогоне являются виртуальными и, следовательно, не могут быть поддельными, вам нужно будет использовать шаблон фасада , чтобы обернуть взаимодействие SiteCore, чтобы сделать его более удобным для тестирования.

public class SiteCorePostsFacade {

  SiteCorePosts m_Posts = new SiteCorePosts();

  //important - make this method virtual so it can be mocked without needing an interface
  public virtual IEnumerable<Post> GetPostsByUser(int userId) {
    return m_Posts.GetPostsByUser(userId);
  }
}

Затем вы переходите к использованию SiteCorePostsFacade как будто это интерфейс в предыдущем примере.Хорошая особенность MOQ заключается в том, что он позволяет имитировать конкретные классы с помощью виртуальных методов, а не только интерфейсов.

При таком подходе вы должны иметь возможность вводить все виды данных в свое приложение для проверки всех взаимодействий с SiteCore.API.

1 голос
/ 13 июля 2010

Краткий ответ: Вам необходимо смоделировать звонки на SiteCore CMS.

Длинный ответ: Я не в курсе о SiteCore CMS. Но из твоего вопроса похоже, что это что-то внешнее для твоего приложения. Внешние компоненты вашей системы всегда должны использоваться через интерфейс. Это имеет два преимущества:

  1. Если вы хотите использовать другую систему CMS, вы можете легко это сделать, поскольку ваше приложение просто общается с интерфейсом.
  2. Помогает вам в тестировании поведения, издеваясь над интерфейсом.

Код, который вы пишете, является вашей ответственностью, и, следовательно, вы должны только тестировать этот фрагмент кода. Ваши модульные тесты должны гарантировать, что ваш код вызывает соответствующие методы SiteCode CMS в различных сценариях (поведенческие тесты). Вы можете сделать это с помощью насмешек. Я использую moq для насмешек.

1 голос
/ 13 июля 2010

мы использовали пользовательский WebControl, размещенный в WebForm для наших интеграционных тестов, уже несколько лет, что оборачивает функциональность бегуна NUnit Test Suite во многом как графический интерфейс NUnit. Он показывает симпатичную сетку выполненных тестов со ссылками на приборы и категории для выполнения определенных тестов. Он создан так же, как описано здесь http://adeneys.wordpress.com/2010/04/13/new-technique-for-unit-testing-renderings-in-sitecore/ (пользовательская часть для запуска тестов). Наша реализация также может возвращать необработанный NUnit xml для дальнейшей обработки, например, сервером сборки.

Я пробовал MSTest некоторое время назад, и он также работает, когда указано, что он должен запустить сайт WebDev / IIS для тестирования. Это работает, но очень медленно по сравнению с вышеупомянутым решением.

Счастливого тестирования!

0 голосов
/ 05 августа 2015

Мне удалось заставить модульные тесты взаимодействовать с api sitecore в VS 2015. Этот же тест вызывает исключение StackOverflow при запуске в VS 2012.

Например, этот вызов метода работает нормально в VS2015, но не в VS2015:

Context.SetActiveSite("mysite");

краткое примечание: предполагается, что у вас есть сайт с именем mysite setup в вашем конфигурационном файле

0 голосов
/ 13 июля 2010

Как сказал Тугга, это зависит от того, насколько тесно код, который вы хотите протестировать, связан с SiteCore.Если это что-то вроде:

SomeSiteCoreService siteCoreDependency = new SomeSiteCoreService()

, тогда это будет очень сложно проверить.Если SiteCore предоставляет вам интерфейс, то у вас есть больше возможностей для его модульного тестирования.Вы можете передать реализацию в ваш метод (contstructor, свойство класса или параметр метода), а затем отправить ложную реализацию этой службы.

Если они не предоставляют вам интерфейс, то вынужно сделать немного больше работы.Вы должны написать собственный интерфейс адаптера, а реализация по умолчанию делегирует сторонней зависимости.

открытый интерфейс ICMSAdapter {void DoSomethingWithCMS ()
}

открытый класс SiteCoreCMSAdapter: ICMSAdapter{SiteCoreService _cms = new SiteCoreService ();public void DoSomethingWithCMS () {_cms.DoSomething ();}

Это позволяет вашим сторонним зависимостям держаться на расстоянии вытянутой руки и обеспечивать швы для всякого рода классных вещей, таких как модульные тесты, а также вы делаете архитектуру стиля перехвата и делаете свое дело до и после вызова.}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...