gpt4 book ai didi

c# - 创建新对象的单元测试 void 方法

转载 作者:太空狗 更新时间:2023-10-29 18:20:55 24 4
gpt4 key购买 nike

我有如下方法:

public void ExecuteSomeCommand()
{
new MyCommand( someInt, SomeEnum.EnumValue ).Execute();
}

我想测试传递到我正在创建的 ICommand 对象的构造函数中的枚举值是否正确。有什么方法可以用 Rhino.Mocks 做到这一点吗?

最佳答案

选项 1:使用接缝

最简单的方法是用接缝重构该方法:

public void ExecuteSomeCommand()
{
this.CreateCommand(someInt, SomeEnum.EnumValue).Execute();
}

// Your seam
protected virtual ICommand CreateCommand(int someInt,
SomeEnum someEnum)
{
return new MyCommand(someInt, SomeEnum.EnumValue);
}

这样您就可以通过扩展此类来拦截"new"运算符的创建。手动执行此操作时,它可能看起来像这样:

public FakeSomeService : SomeService
{
public int SomeInt;
public SomeEnum SomeEnum;

protected override Command CreateCommand(int someInt,
SomeEnum someEnum)
{
this.SomeInt = someInt;
this.SomeEnum = someEnum;
return new FakeCommand();
}

private sealed class FakeCommand : Command
{
public override void Execute() { }
}
}

这个假类可以用在你的测试方法中。


选项 2:分离行为和数据

更好的方法 是将数据与行为分开。您的命令同时具有数据(消息)和行为(处理该消息)。如果您被允许在您的代码库中进行这样的更改:将其分开,例如通过定义命令和命令处理程序。这是一个例子:

// Define an interface for handling commands
public interface IHandler<TCommand>
{
void Handle(TCommand command);
}

// Define your specific command
public class MyCommand
{
public int SomeInt;
public SomeEnum SomeEnum;
}

// Define your handler for that command
public class MyCommandHandler : IHandler<MyCommand>
{
public void Handle(MyCommand command)
{
// here your old execute logic
}
}

现在您可以使用依赖注入(inject)将处理程序注入(inject)到您希望测试的类中。这个类现在看起来像这样:

public class SomeService
{
private readonly IHandler<MyCommand> handler;

// Inject a handler here using constructor injection.
public SomeService(IHandler<MyCommand> handler)
{
this.handler = handler;
}

public void ExecuteSomeCommand()
{
this.handler.Handle(new MyCommand
{
SomeInt = someInt,
SomeEnum = someEnum
});
}
}

由于您现在已将数据与行为分开,因此创建一个伪造的命令处理程序(或使用 Rhino 模拟创建它)来检查是否向处理程序发送了正确的命令将非常容易。手动这看起来像这样:

public class FakeHandler<TCommand> : IHandler<TCommand>
{
public TCommand HandledCommand { get; set; }

public void Handle(TCommand command)
{
this.HandledCommand = command;
}
}

这个假处理程序可以在整个单元测试项目中重复使用。使用此 FakeHandler 的测试可能看起来像这样:

[TestMethod]
public void SomeTestMethod()
{
// Arrange
int expected = 23;

var handler = new FakeHandler<MyCommand>();

var service = new SomeService(handler);

// Act
service.ExecuteSomeCommand();

// Assert
Assert.AreEqual(expected, handler.HandledCommand.SomeInt);
}

将数据与行为分开不仅可以使您的应用程序更易于测试。它使您的应用程序更能适应变化。例如,可以将横切关注点添加到命令的执行中,而无需更改系统中的任何处理程序。因为IHandler<T>是一个只有一个方法的接口(interface),很容易写一个decorator它可以包装每个处理程序并添加诸如日志记录、审计跟踪、分析、验证、事务处理、容错改进等内容。您可以在 this article 中阅读更多相关信息。 .

关于c# - 创建新对象的单元测试 void 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5962639/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com