单元测试 – 我可以单元测试一个使Sitecore上下文调用的方法吗?

我正在开发一个通过Sitecore CMS构建的Web应用程序.我想知道我们是否可以进行单元测试,例如从Sitecore获取一些数据的方法对其进行一些处理并吐出结果.我想通过单元测试来测试方法中的所有逻辑.

在搜索互联网后,我非常困惑.有人说这种测试实际上是集成测试而不是单元测试,我应该只测试没有Sitecore调用的代码,其他人说这是不可能的,因为Sitecore上下文会丢失.

我想请求经验丰富的同事们给你的帮助:
我可以单元测试包含Sitecore调用的方法吗?如果是,怎么样?如果不是,为什么?有没有解决方法?

该项目刚刚开始,因此在选择MSTest或Nunit等单元测试框架时,如果解决方案与选择的单元测试框架相关,则没有问题.

最佳答案
如果没有提供电子邮件和通过销售宣传生活,很难找到关于Sitecore的任何信息,所以我将提供一个关于如何做这样的事情的通用方法.

首先,您假设Sitecore API保证可以正常工作 – 即它是一个框架 – 并且您不对它进行单元测试.您应该对您的交互进行单元测试.

然后,download MOQ并阅读quick start on how to use it.这是我首选的模拟框架.如果您愿意,请随意使用其他框架.

希望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);
}

在这种情况下,单元测试应该相当容易.通过一些依赖注入,您可以将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实际上不是一个接口,并且是一个具体的类,其方法不是虚拟的,因此无法模拟,您将需要使用Facade pattern来包装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的所有交互.

转载注明原文:单元测试 – 我可以单元测试一个使Sitecore上下文调用的方法吗? - 代码日志