Testy z nunit
Zaczynam od TDD i sam mogę rozwiązać większość problemów, z którymi się borykałem. Ale teraz jestem zagubiony: jak mogę sprawdzić, czy zdarzenia są zwolnione? Szukałem czegoś w stylu Assert.Raise
LUB Assert.Fire
, ale nic nie ma. Google nie było zbyt przydatne, większość trafień były sugestie jak foo.myEvent += new EventHandler(bar); Assert.NotNull(foo.myEvent);
, ale to niczego nie dowodzi.
9 answers
Sprawdzenie, czy zdarzenia zostały wywołane, można wykonać zapisując się do tego zdarzenia i ustawiając wartość logiczną:
var wasCalled = false;
foo.NyEvent += (o,e) => wasCalled = true;
...
Assert.IsTrue(wasCalled);
Z powodu prośby - BEZ lambda:
var wasCalled = false;
foo.NyEvent += delegate(o,e){ wasCalled = true;}
...
Assert.IsTrue(wasCalled);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-03 17:04:59
Wolę robić co następuje:
var wait = new AutoResetEvent(false);
foo.MeEvent += (sender, eventArgs) => { wait.Set(); };
Assert.IsTrue(wait.WaitOne(TimeSpan.FromSeconds(5)));
Zalety: obsługuje scenariusz wielowątkowy (jeśli handler jest wywoływany w innym wątku)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-10 11:49:14
Jeśli wiesz, że zdarzenie zostanie wywołane synchronicznie:
bool eventRaised = false;
Customer customer = new Customer() { Name = "Carl" };
customer.NameChanged += (sender, e) => { eventRaised = true; };
customer.Name = "Sam";
Assert.IsTrue(eventRaised);
Jeżeli zdarzenie może być wywołane asynchronicznie:
ManualResetEvent eventRaised = new ManualResetEvent(false);
Customer customer = new Customer() { Name = "Carl" };
customer.NameChanged += (sender, e) => { eventRaised.Set(); };
customer.Name = "Sam";
Assert.IsTrue(eventRaised.WaitOne(TIMEOUT));
Jednak niektórzy twierdzą, że należy unikać testowania asynchronicznego zachowania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-05 18:11:49
Ostatnio musiałem to zrobić, a poniżej jest to, co wymyśliłem. Powodem, dla którego nie zrobiłem tego, co mówili inni posty, jest to, że nie podoba mi się idea zmiennej utrzymanie stanu i konieczności resetowania go "ręcznie" między wieloma zdarzeniami.
Poniżej znajduje się kod zdarzenia ClassUnderTest
z NameChanged
, które jest testowane wMyTests
testach:
public class ClassUnderTest {
private string name;
public string Name {
get { return this.name; }
set {
if (value != this.name) {
this.name = value;
NameChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
public event EventHandler<PropertyChangedEventArgs> NameChanged = delegate { };
}
[TestFixture]
public class MyTests {
[Test]
public void Test_SameValue() {
var t = new ClassUnderTest();
var e = new EventHandlerCapture<PropertyChangedEventArgs>();
t.NameChanged += e.Handler;
Event.Assert(e, Event.IsNotRaised<PropertyChangedEventArgs>(), () => t.Name = null);
t.Name = "test";
Event.Assert(e, Event.IsNotRaised<PropertyChangedEventArgs>(), () => t.Name = "test");
}
[Test]
public void Test_DifferentValue() {
var t = new ClassUnderTest();
var e = new EventHandlerCapture<PropertyChangedEventArgs>();
t.NameChanged += e.Handler;
Event.Assert(e, Event.IsPropertyChanged(t, "Name"), () => t.Name = "test");
Event.Assert(e, Event.IsPropertyChanged(t, "Name"), () => t.Name = null);
}
}
Klasy pomocnicze są poniżej. Klasy mogą być używane z dowolnymi EventHandler<TEventArgs>
lub rozszerzane na inne delegaty. Testy zdarzeń mogą być zagnieżdżane.
/// <summary>Class to capture events</summary>
public class EventHandlerCapture<TEventArgs> where TEventArgs : EventArgs {
public EventHandlerCapture() {
this.Reset();
}
public object Sender { get; private set; }
public TEventArgs EventArgs { get; private set; }
public bool WasRaised { get; private set; }
public void Reset() {
this.Sender = null;
this.EventArgs = null;
this.WasRaised = false;
}
public void Handler(object sender, TEventArgs e) {
this.WasRaised = true;
this.Sender = sender;
this.EventArgs = e;
}
}
/// <summary>Contains things that make tests simple</summary>
public static class Event {
public static void Assert<TEventArgs>(EventHandlerCapture<TEventArgs> capture, Action<EventHandlerCapture<TEventArgs>> test, Action code) where TEventArgs : EventArgs {
capture.Reset();
code();
test(capture);
}
public static Action<EventHandlerCapture<TEventArgs>> IsNotRaised<TEventArgs>() where TEventArgs : EventArgs {
return (EventHandlerCapture<TEventArgs> test) => {
NUnit.Framework.Assert.That(test.WasRaised, Is.False);
};
}
public static Action<EventHandlerCapture<PropertyChangedEventArgs>> IsPropertyChanged(object sender, string name) {
return (EventHandlerCapture<PropertyChangedEventArgs> test) => {
NUnit.Framework.Assert.That(test.WasRaised, Is.True);
NUnit.Framework.Assert.That(test.Sender, Is.SameAs(sender));
NUnit.Framework.Assert.That(test.EventArgs.PropertyName, Is.EqualTo(name));
};
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-17 17:49:47
Używając NUnit i Moq możesz wykonać bardziej solidne testowanie zdarzeń.
Klasa Mocka używana do monitorowania wyzwalaczy zdarzeń:
public class AssertEvent { public virtual void Call(string obj) { } }
Mock<AssertEvent> EventMock;
AssertEvent Evt;
Konfiguracja wyzwalaczy zdarzeń:
[SetUp]
public void TestInit() {
EventMock = new Mock<AssertEvent>();
Evt= EventMock.Object;
}
Używanie Mock obiektów w testach:
[Test]
public void TestMethod() {
myObject.Event1 += (sender, args) => Evt.Call("Event1Label");
myObject.Event2 += (sender, args) => Evt.Call("Event2Label");
myObject.Event3 += (sender, args) => Evt.Call("Event3Label");
myObject.SomeEventTrigger();
EventMock.Verify(m => m.Call("Event1Label"), Times.Exactly(1));
EventMock.Verify(m => m.Call("Event2Label"), Times.Never());
EventMock.Verify(m => m.Call("Event3Label"), Times.Between(1,3);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-15 04:03:54
Nie zrobiłem tego osobiście, ale może mógłbyś dodać atrapę obsługi zdarzenia do zdarzenia, które chcesz subskrybować i poprosić go o aktualizację lokalnej zmiennej logicznej, aby po wywołaniu metody można było sprawdzić stan tego zdarzenia logicznego, aby zobaczyć, czy zdarzenie zostało wywołane?
Coś w stylu:
bool eventFired = false;
foo.MyEvent += (s, e) => { eventFired = true };
Assert.IsTrue(eventFired);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-02 11:16:00
@theberningmonk: brakuje";". Poprawiona wersja to:
bool eventFired = false;
foo.MyEvent += (s, e) => { eventFired = true; };
Assert.IsTrue(eventFired);
Zdrówko! ;-)Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-02 11:51:20
Użyłbym FluentAssertions razem z Nunit : https://fluentassertions.com/eventmonitoring to działa naprawdę dobrze. Oto przykład z docs
var subject = new EditCustomerViewModel();
using (var monitoredSubject = subject.Monitor())
{
subject.Foo();
monitoredSubject.Should().Raise("NameChangedEvent");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-11 11:00:07
Możesz dodać niestandardową obsługę zdarzeń, która na przykład zwiększa pole integer w klasie przypadków testowych. A następnie sprawdź, czy pole zostało zwiększone.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-02 11:14:21