使用第三方对象实例化测试代码
Testing Code with Third Party Object Instantiation
单元测试的新手,并试图让我的头脑围绕一段代码进行一些简单的测试,如果它不存在(在 Umbraco 8 中),则获取或创建一个模板。
方法很简单,调用Initialise时获取模板,如果不存在则创建:
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Components
{
public class TemplateComponent : IComponent
{
private readonly IFileService _fileService;
public TemplateComponent(IFileService fileService)
{
_fileService = fileService;
}
public void Initialize()
{
ITemplate blogTemplate = _fileService.GetTemplate("aldusBlog");
if (blogTemplate == null)
{
blogTemplate = new Template("Aldus Blog", "aldusBlog");
_fileService.SaveTemplate(blogTemplate);
}
}
public void Terminate() { }
}
}
工作正常,没问题。
我正在尝试编写一些测试,首先检查 _fileService.GetTemplate
是否被调用。
第二个测试应该检查 _fileService.SaveTemplate()
在 returns 为 null 时被调用。
using Moq;
using NUnit.Framework;
using Papermoon.Umbraco.Aldus.Core.Components;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Tests.Components
{
[TestFixture]
public class TemplateComponentTests
{
private Mock<IFileService> _fileService;
private TemplateComponent _component;
[SetUp]
public void SetUp()
{
_fileService = new Mock<IFileService>();
_component = new TemplateComponent(_fileService.Object);
}
[Test]
public void Initialise_WhenCalled_GetsBlogTemplate()
{
_component.Initialize();
_fileService.Verify(s => s.GetTemplate("aldusBlog"), Times.Once);
}
[Test]
public void Initialise_BlogTemplateDoesNotExist_CreateTemplate()
{
_fileService
.Setup(s => s.GetTemplate("aldusBlog"))
.Returns((ITemplate) null);
_component.Initialize();
_fileService.Verify(s => s.SaveTemplate(It.Is<ITemplate>(p => p.Alias == "aldusBlog"), -1), Times.Once());
}
}
}
我这样做的麻烦是 blogTemplate = new Template("Aldus Blog", "aldusBlog");
抛出错误:
Can not get Current.Config during composition. Use composition.Config.
我认为这是因为我没有任何背景让我认为 ITemplate
需要被嘲笑。但是,因为new Template("Aldus Blog", "aldusBlog");
总会被调用,所以总会抛出这个错误。
显然代码不是防弹的,那么我如何重构它以使其可测试?
第 3 方 class 可能与在单独进行单元测试时不存在或未配置的实现问题紧密耦合。
将对象创建抽象到工厂中。
public interface ITemplateFactory {
ITemplate Create(string name, string alias);
}
其实现可以在 运行 时注入
public class DefaultTemplateFactory : ITemplateFactory {
public ITemplate Create(string name, string alias) {
return new Template(name, alias);
}
}
前提是在启动时在组合根目录下注册
这现在允许组件松散耦合,远离实现问题
public class TemplateComponent : IComponent {
private readonly IFileService fileService;
private readonly ITemplateFactory templateFactory;
public TemplateComponent(IFileService fileService, ITemplateFactory templateFactory) {
this.fileService = fileService;
this.templateFactory = templateFactory;
}
public void Initialize() {
ITemplate blogTemplate = fileService.GetTemplate("aldusBlog");
if (blogTemplate == null) {
blogTemplate = templateFactory.Create("Aldus Blog", "aldusBlog");
fileService.SaveTemplate(blogTemplate);
}
}
public void Terminate() { }
}
隔离测试时可以根据需要更换
[TestFixture]
public class TemplateComponentTests {
private Mock<IFileService> fileService;
private Mock<ITemplateFactory> templateFactory;
private TemplateComponent component;
string templateAlias = "aldusBlog";
[SetUp]
public void SetUp() {
//Arrange
fileService = new Mock<IFileService>();
templateFactory = new Mock<ITemplateFactory>();
templateFactory.Setup(_ => _.Create(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string name, string alias) =>
Mock.Of<ITemplate>(_ => _.Alias == alias && _.Name == name)
);
component = new TemplateComponent(fileService.Object, templateFactory.Object);
}
[Test]
public void Initialise_WhenCalled_GetsBlogTemplate() {
//Act
component.Initialize();
//Assert
fileService.Verify(s => s.GetTemplate(templateAlias), Times.Once);
}
[Test]
public void Initialise_BlogTemplateDoesNotExist_CreateTemplate() {
//Act
component.Initialize();
//Assert
fileService.Verify(s => s.SaveTemplate(It.Is<ITemplate>(p => p.Alias == templateAlias), 0), Times.Once());
}
}
单元测试的新手,并试图让我的头脑围绕一段代码进行一些简单的测试,如果它不存在(在 Umbraco 8 中),则获取或创建一个模板。
方法很简单,调用Initialise时获取模板,如果不存在则创建:
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Components
{
public class TemplateComponent : IComponent
{
private readonly IFileService _fileService;
public TemplateComponent(IFileService fileService)
{
_fileService = fileService;
}
public void Initialize()
{
ITemplate blogTemplate = _fileService.GetTemplate("aldusBlog");
if (blogTemplate == null)
{
blogTemplate = new Template("Aldus Blog", "aldusBlog");
_fileService.SaveTemplate(blogTemplate);
}
}
public void Terminate() { }
}
}
工作正常,没问题。
我正在尝试编写一些测试,首先检查 _fileService.GetTemplate
是否被调用。
第二个测试应该检查 _fileService.SaveTemplate()
在 returns 为 null 时被调用。
using Moq;
using NUnit.Framework;
using Papermoon.Umbraco.Aldus.Core.Components;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Tests.Components
{
[TestFixture]
public class TemplateComponentTests
{
private Mock<IFileService> _fileService;
private TemplateComponent _component;
[SetUp]
public void SetUp()
{
_fileService = new Mock<IFileService>();
_component = new TemplateComponent(_fileService.Object);
}
[Test]
public void Initialise_WhenCalled_GetsBlogTemplate()
{
_component.Initialize();
_fileService.Verify(s => s.GetTemplate("aldusBlog"), Times.Once);
}
[Test]
public void Initialise_BlogTemplateDoesNotExist_CreateTemplate()
{
_fileService
.Setup(s => s.GetTemplate("aldusBlog"))
.Returns((ITemplate) null);
_component.Initialize();
_fileService.Verify(s => s.SaveTemplate(It.Is<ITemplate>(p => p.Alias == "aldusBlog"), -1), Times.Once());
}
}
}
我这样做的麻烦是 blogTemplate = new Template("Aldus Blog", "aldusBlog");
抛出错误:
Can not get Current.Config during composition. Use composition.Config.
我认为这是因为我没有任何背景让我认为 ITemplate
需要被嘲笑。但是,因为new Template("Aldus Blog", "aldusBlog");
总会被调用,所以总会抛出这个错误。
显然代码不是防弹的,那么我如何重构它以使其可测试?
第 3 方 class 可能与在单独进行单元测试时不存在或未配置的实现问题紧密耦合。
将对象创建抽象到工厂中。
public interface ITemplateFactory {
ITemplate Create(string name, string alias);
}
其实现可以在 运行 时注入
public class DefaultTemplateFactory : ITemplateFactory {
public ITemplate Create(string name, string alias) {
return new Template(name, alias);
}
}
前提是在启动时在组合根目录下注册
这现在允许组件松散耦合,远离实现问题
public class TemplateComponent : IComponent {
private readonly IFileService fileService;
private readonly ITemplateFactory templateFactory;
public TemplateComponent(IFileService fileService, ITemplateFactory templateFactory) {
this.fileService = fileService;
this.templateFactory = templateFactory;
}
public void Initialize() {
ITemplate blogTemplate = fileService.GetTemplate("aldusBlog");
if (blogTemplate == null) {
blogTemplate = templateFactory.Create("Aldus Blog", "aldusBlog");
fileService.SaveTemplate(blogTemplate);
}
}
public void Terminate() { }
}
隔离测试时可以根据需要更换
[TestFixture]
public class TemplateComponentTests {
private Mock<IFileService> fileService;
private Mock<ITemplateFactory> templateFactory;
private TemplateComponent component;
string templateAlias = "aldusBlog";
[SetUp]
public void SetUp() {
//Arrange
fileService = new Mock<IFileService>();
templateFactory = new Mock<ITemplateFactory>();
templateFactory.Setup(_ => _.Create(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string name, string alias) =>
Mock.Of<ITemplate>(_ => _.Alias == alias && _.Name == name)
);
component = new TemplateComponent(fileService.Object, templateFactory.Object);
}
[Test]
public void Initialise_WhenCalled_GetsBlogTemplate() {
//Act
component.Initialize();
//Assert
fileService.Verify(s => s.GetTemplate(templateAlias), Times.Once);
}
[Test]
public void Initialise_BlogTemplateDoesNotExist_CreateTemplate() {
//Act
component.Initialize();
//Assert
fileService.Verify(s => s.SaveTemplate(It.Is<ITemplate>(p => p.Alias == templateAlias), 0), Times.Once());
}
}