简体   繁体   English

如何对SharePoint加载项进行单元测试?

[英]How to unit test a SharePoint Add-in?

I would like to remove the SharePoint dependencies and mock them out. 我想删除SharePoint依赖项并将其模拟出来。 The default Index action loos like the following in the new SharePoint add-in template: 在新的SharePoint加载项模板中,默认的Index操作如下所示:

    public ActionResult Index()
    {
        User spUser = null;
        var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
        using (var clientContext = spContext.CreateUserClientContextForSPHost())
        {
            if (clientContext != null)
            {
                spUser = clientContext.Web.CurrentUser;
                clientContext.Load(spUser, user => user.Title);
                clientContext.ExecuteQuery();
                ViewBag.UserName = spUser.Title;
            }
        }
        return View();
    }

I have tried to package the ClientContext into an adapter, but cannot mock out Web property: 我试图将ClientContext打包到适配器中,但是无法模拟Web属性:

public interface IClientContext
{
    Web Web { get; }
    void Load<T>(T clientObject, params Expression<Func<T, object>>[] retrievals) where T : ClientObject;
    void ExecuteQuery();
}

public class ClientContextAdapter : IClientContext
{
    private readonly ClientContext _wrappedClient;
    public ClientContextAdapter(ClientContext client)
    {
        _wrappedClient = client;
    }

    public Web Web => _wrappedClient.Web;

    public void Load<T>(T clientObject, params Expression<Func<T, object>>[] retrievals) where T : ClientObject
    {
        _wrappedClient.Load(clientObject, retrievals);
    }
    public void ExecuteQuery()
    {
        _wrappedClient.ExecuteQuery();
    }
}

How do you unit test your SharePoint add-ins? 如何对SharePoint加载项进行单元测试?

Found a solution, so SharePoint dependency can mocked out in the following way. 找到了一个解决方案,因此可以通过以下方式模拟SharePoint依赖性。 Web should be packed into an adapter as well: Web也应打包到适配器中:

public interface IWeb
{
    User CurrentUser { get; }
}

public class WebAdapter : IWeb
{
    private readonly Web _wrappedClient;
    public WebAdapter(Web client)
    {
        _wrappedClient = client;
    }

    public User CurrentUser => _wrappedClient.CurrentUser;
}

ClientContext adapter with Web adapter inside: 带有Web适配器的ClientContext适配器:

public interface IClientContext
{
    IWeb Web { get; }
    void Load<T>(T clientObject, params Expression<Func<T, object>>[] retrievals) where T : ClientObject;
    void ExecuteQuery();
}

public class ClientContextAdapter : IClientContext
{
    private readonly ClientContext _wrappedClient;
    public ClientContextAdapter(ClientContext client)
    {
        _wrappedClient = client;
    }

    public IWeb Web => new WebAdapter(_wrappedClient.Web);

    public void Load<T>(T clientObject, params Expression<Func<T, object>>[] retrievals) where T : ClientObject
    {
        _wrappedClient.Load(clientObject, retrievals);
    }

    public void ExecuteQuery()
    {
        _wrappedClient.ExecuteQuery();
    }
}

ClientContext dependency removed from HomeController with poor man's dependency injection: 通过较差的依赖注入将ClientContext依赖从HomeController中删除:

     IClientContext _clientContext;

    #region Constructors
    public HomeController()
    {
        // Called by MVC
    }

    public HomeController(IClientContext clientContext)
    {
        _clientContext = clientContext;
    }
    #endregion

    [SharePointContextFilter]
    public ActionResult Index()
    {
        if (_clientContext == null)
        {
            var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
            _clientContext = new ClientContextAdapter(spContext.CreateUserClientContextForSPHost());
        }

        if (_clientContext != null)
        {
            User spUser = _clientContext.Web.CurrentUser;
            _clientContext.Load(spUser, user => user.Title);
            _clientContext.ExecuteQuery();
            ViewBag.UserName = spUser.Title;
        }

        return View();
    }

The unit test of Index action with Moq and FluentAssertions: Moq和FluentAssertions的索引动作的单元测试:

[TestClass]
class HomeControllerTests
{
    private HomeController _homeController;

    [TestInitialize]
    public void Init()
    {
        // Arrange
        var user = new User(new ClientContext("http://localhost"), 
            new ObjectPathConstructor(new ClientContext("http://localhost"), string.Empty, null));
        user.Title = "TestUser";
        var mockWeb = new Mock<IWeb>();
        mockWeb.SetupGet(w => w.CurrentUser).Returns(user);
        var mockClient = new Mock<IClientContext>();
        mockClient.SetupGet(c => c.Web).Returns(mockWeb.Object);

        _homeController = new HomeController(mockClient.Object);
    }

    [TestMethod]
    public void Index()
    {
        // Act
        var result = (ViewResult)_homeController.Index();

        // Assert
        result.Should().BeViewResult();
        string userName = result.ViewBag.UserName;
        userName.Should().Be("TestUser");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM