Seçenek 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);
}
sen kesmek Bu şekilde: Bir bir dikiş
kolay yolu bir dikişle bu yöntemi refactor olduğunu kullanın Bu sınıfı genişleterek 'yeni' operatörün oluşturulması. elle Bunu yaparken, bu gibi görünebilir:
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() { }
}
}
Bu sahte sınıf
test yöntemlerinde kullanılabilir.
Seçenek 2: Ayrı davranışı ve veri
daha iyi bir yol davranış verileri ayrı olacaktır. Komutun hem verileri (mesajı) hem de davranışı vardır (bu iletiyi işlerken). Kod tabanınızda böyle bir değişiklik yapmanıza izin verilirse: örneğin, komutları ve komut işleyicilerini tanımlayarak bunu ayırın.
// 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
}
}
Şimdi test etmek istediğiniz sınıfa bir işleyici enjekte etmek
bağımlılık enjeksiyon kullanabilirsiniz: İşte bir örnek. Bu sınıf artık şu şekilde görünecektir: Şimdi davranış verileri, sahte komut işleyicisi oluşturmak çok kolay olacak ayrılmış yana
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
});
}
}
(veya Rhino alay kullanarak oluşturun) kontrol ettiğinden doğru komuta eğer işleyiciye gönderildi. Bu, aşağıdaki gibi olacaktır:
public class FakeHandler<TCommand> : IHandler<TCommand>
{
public TCommand HandledCommand { get; set; }
public void Handle(TCommand command)
{
this.HandledCommand = command;
}
}
Bu sahte işleyici ünite test projenizde yeniden kullanılabilir. Bu gibi görünebilir bu FakeHandler
kullanarak bir test:
[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);
}
davranış verileri ayırmak uygulama daha sınanabilir yapar sadece. Uygulamanızı değiştirmek için daha esnek hale getirir. Örneğin, sistemdeki herhangi bir işleyicide değişiklik yapmak zorunda kalmadan komutların yürütülmesine çapraz kesim endişeleri eklenebilir.IHandler<T>
, tek bir yöntemle bir arabirim olduğundan, her işleyiciyi sarmalayabilen ve günlüğe kaydetme, denetim takibi, profil oluşturma, doğrulama, işlem işleme, hataya dayanıklılık geliştiricileri vb. Gibi şeyler ekleyen bir decorator yazmak çok kolaydır. Bu konuda this article.
Enum değeri beklenmiyorsa kurucu bir istisna atar mı? – MattDavey
Yapıcının kendisi atmıyor. Argümanlar Execute yöntemi tarafından bir NavigationManager sınıfı aracılığıyla oluşturulan bir görünümün modeline geçirilir. Yeni görünüm modeli daha sonra bazı görüntüleme özelliklerinin enumunu kullanır ve beklenmedik bir değer ise atar. – alimbada