如何在ASP中使用WebImage对控制器进行单元测试.. Net MVC应用
本文关键字:控制器 单元测试 Net 应用 MVC WebImage ASP | 更新日期: 2023-09-27 18:15:37
我有这个非常简单的方法在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,或重构它更可测试?谢谢。
几点:
- 方法名以"Get"开头,方法不返回任何东西。
- 当你在
GetProfileImage
内更新图像时,你应该测试这些更新是否正确完成。这是您编写单元测试时要针对的一种情况。 - 为了测试方法的行为(例如,图像的最大透明度设置为250),你应该返回图像对象。
我在这上面花了很长时间,但这对我来说是一次很好的学习经历。我是这样做的:
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);
}
这个工厂接口的实际实现,将被Ninject注入到控制器中,看起来像这样:
public class WebImageFactory : IWebImageFactory
{
public IWebImage Get(byte[] data)
{
return new WebImageWrapper(data);
}
}
最后,我的控制器方法现在看起来像这样:
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);
}
唷!做了很多工作,但对我来说,这是一个很好的学习经验,如果我再次需要这个代码,我就有了。我也希望它能对其他有这种担忧的人有用。