如何在ASP中使用WebImage对控制器进行单元测试。 Net MVC App

时间:2014-07-30 01:07:24

标签: c# asp.net-mvc unit-testing moq

我在MVC控制器中有这个非常简单的方法:

    public void GetProfileImage(int id)
    {
        var data = _companyService.GetProfileImage(id);

        if (data == null)
            return;

        var image = new WebImage(data).ResizeMaxPreserveTransparency(250, 250);
        image.Write();
    }

有没有人对我如何测试它,模拟WebImage或重构它以使其更易测试?谢谢。

2 个答案:

答案 0 :(得分:0)

几点:

  1. 方法名称以“Get”开头,方法不返回任何内容。
  2. 在更新GetProfileImage内的图片时,您应该测试这些更新是否正确完成。这是你将编写单元测试的情况之一。
  3. 为了测试方法行为(例如,图像最大透明度设置为250),您应该返回图像对象。
  4. 希望这有帮助。

答案 1 :(得分:0)

我花了太长时间,但这对我来说是一次非常好的学习经历。我是这样做的:

1)创建一个包装我需要的WebImage的方法和属性的接口:

 public interface IWebImage
 { 
    void Write(string requestedFormat = null);

    string ImageFormat { get; }

    int Width { get; }

    int Height { get; }

    byte[] GetBytes(string requestedFormat = null);

    IWebImage Resize(int width, int height, bool preserveAspectRatio = true, bool preventEnlarge = false);
}

2)创建一个实现此接口的包装器,它是实际WebImage的包装器:

 public class WebImageWrapper : IWebImage
 {
    private readonly WebImage _instance;

    public WebImageWrapper(byte[] data)
    {
        _instance = new WebImage(data);
    }

    public WebImageWrapper(WebImage image)
    {
        _instance = image;
    }

    public void Write(string requestedFormat = null)
    {
        _instance.Write(requestedFormat);
    }

    public string ImageFormat { get { return _instance.ImageFormat; } }

    public int Width { get { return _instance.Width; } }

    public int Height { get { return _instance.Height; } }

    public byte[] GetBytes(string requestedFormat = null)
    {
        return _instance.GetBytes(requestedFormat);
    }

    public IWebImage Resize(int width, int height, bool preserveAspectRatio = true, bool preventEnlarge = false)
    {
        return new WebImageWrapper(_instance.Resize(width, height, preserveAspectRatio, preventEnlarge));
    }
}

3)为工厂创建一个接口,可以模拟它以提供模拟的IWebImage,也可以注入以提供实际的WebImageWrapper。

public interface IWebImageFactory
{
    IWebImage Get(byte[] data);
}

4)这个工厂接口的实际实现,将由Ninject注入控制器,如下所示:

public class WebImageFactory : IWebImageFactory
{
    public IWebImage Get(byte[] data)
    {
        return new WebImageWrapper(data);
    }
}

5)最后,我的控制器方法现在看起来像这样:

    public void GetProfileImage(int? id)
    {
        var data = _companyService.GetProfileImage(id);

        if (data == null)
            return;

        var image = WebImageFactory.Get(data).ResizeMaxPreserveTransparency(250, 250);
        image.Write();
    }

6)WebImageFactory是一个注入属性,所以我可以提供我想要的任何模拟,这反过来可以提供一个模拟的IWebImage。从现在开始,创建单元测试是微不足道的。

    [TestMethod]
    public void GetProfileImageTest()
    {
        // Arrange
        var byteArray = new[] {(byte) 12, (byte) 13};
        var image = new Mock<IWebImage>();
        var factory = new Mock<IWebImageFactory>();
        var companyService = new Mock<ICompanyService>();

        companyService.Setup(c => c.GetProfileImage(99)).Returns(byteArray);
        factory.Setup(f => f.Get(byteArray)).Returns(image.Object);
        var target = new CompanyProfileController(Mock.Of<ICompanyProfileService>(), companyService.Object)
        {
            WebImageFactory = factory.Object
        };

        // Act
        target.GetProfileImage(99);

        // Assert
        image.Verify(i => i.Write(null), Times.Once);
    }

呼!很多工作,但同样,对我来说是一个很好的学习经历,如果我再次需要这个代码,我就拥有它。我也希望这对有这种担忧的其他人有用。