I'm using NUnit to test my application, which I've included a simplified version of below. I'm looking for a way to fire an event on a mock class, and check that the class under test has received it.
The application calls LogIn on the session, and, some time later, the session fires the OnLoggedIn event. I've set up a mock session, and checked that the app calls LogIn on it. Now I want to fire the OnLoggedIn event on it, and check that the app handles this event.
How can I do this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using NUnit.Mocks;
namespace NUnitTest
{
public delegate void LoggedInDelegate();
public interface ISession
{
void LogIn(String username, String password);
event LoggedInDelegate OnLoggedIn;
}
public class App
{
private bool loggedIn = false;
private ISession sess;
public bool LoggedIn
{
get
{
return loggedIn;
}
}
public App(ISession sess)
{
this.sess = sess;
sess.OnLoggedIn += HandleOnLoggedIn;
}
public void LogIn(String username, String password)
{
sess.LogIn(username, password);
}
public void HandleOnLoggedIn()
{
loggedIn = true;
}
}
[TestFixture]
public class AppTest
{
private String USERNAME = "Username";
private String PASSWORD = "Password";
private DynamicMock mockSess;
private App app;
[SetUp]
public void TestInit()
{
// Create objects.
mockSess = new DynamicMock(typeof(ISession));
app = new App((ISession) mockSess.MockInstance);
}
[Test]
public void TestLogin()
{
mockSess.Expect("LogIn", USERNAME, PASSWORD);
app.LogIn(USERNAME, PASSWORD);
mockSess.Verify();
mockSess.Call("OnLoggedIn");
Assert.IsTrue(app.LoggedIn);
}
}
}
Try this article: https://web.archive.org/web/20110914180329/http://blog.gravityfree.ca/2007/03/raising-events-in-nmock-20.html. I didn't really get it, but I will sit down and try it out later, because I have the same problem.
I usually make an oldfashioned stub object (no mocking framework), and raise the event via a Method call in the stub. It goes something like this:
[TestFixture]
public sealed class TestStubbingEvents
{
[Test]
public void FooReceivesEventFromBar()
{
BarStub bar = new BarStub();
Foo foo = new Foo(bar);
Assert.That(foo.EventReceived, Is.False);
bar.RaiseBarEvent();
Assert.That(foo.EventReceived, Is.True);
}
}
internal class Foo
{
public bool EventReceived
{
get; set;
}
public Foo(IBar bar)
{
EventReceived = false;
bar.BarEvent += ReceiveBarEvent;
}
private void ReceiveBarEvent(object sender, EventArgs args)
{
EventReceived = true;
}
}
internal class BarStub : IBar
{
public event BarEventHandler BarEvent;
//Stub method that invokes the event
public void RaiseBarEvent()
{
BarEvent.Invoke(this, new EventArgs());
}
}
public delegate void BarEventHandler(object sender, EventArgs args);
public interface IBar
{
event BarEventHandler BarEvent;
}
This is the best I've come up with, so I am interested to see what the article in the link can produce.
Added:
Note, that the EventReceived property on the Foo class is just an example on how the event affects the object.
Related
Hello i want to add a feature to my app but i just can't figure out.
i want to pass some arguments or at least 1 argument to EventHandler using subscriber.
That argument will allow me to do some check and then trigger event based on that argument.
public class Client
{
public Client()
{
GameAPI api = new GameAPI();
api.AddedPlayerEvent += Api_ClarkAdded;
api.Do();
}
private void Api_ClarkAdded(object sender, GameAPI.AddedPlayerEvents e)
{
Console.WriteLine("User Clark found");
}
}
public class GameAPI
{
public event EventHandler<AddedPlayerEvents> AddedPlayerEvent;
List<AddedPlayerEvents> AddedPlayers = new List<AddedPlayerEvents>();
public GameAPI()
{
// some code to simulate generating some data
AddedPlayers.Add(new AddedPlayerEvents("Player1","James"));
AddedPlayers.Add(new AddedPlayerEvents("Player2", "Clark"));
AddedPlayers.Add(new AddedPlayerEvents("Player3", "Steve"));
}
public void Do()
{
// simulating code ...
//trigger event
if (AddedPlayers.Any(f => f.Name == "Clark")) /*value Clark should come from client using subsciber or something else*/
{
OnPlayerAdded(AddedPlayers.First(f => f.Name == "Clark"));
}
}
protected virtual void OnPlayerAdded(AddedPlayerEvents e)
{
EventHandler<AddedPlayerEvents> handler = AddedPlayerEvent;
if (handler != null)
{
handler(this, e);
}
}
public class AddedPlayerEvents
{
public string Pseudo { get; set; }
public string Name { get; set; }
public AddedPlayerEvents(string pseudo, string name)
{
Pseudo = pseudo;
Name = name;
}
}
}
This is a simplified version of what i want to do so i try to make it simple so you can deal with it without garbadge stuff.
I already made a search but all i can find is the parameters is visible only in the client in the Methode handler not transmitted to the EventHandler, i think t should be stored somewhere that he can fetch for them.
Thanks in advance.
Update:
Thanks for the clarification. I think you don't fully understand how the event subscription mechanism works. Let me explain this on example. I refactored your code a little bit:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
Client client = new Client();
}
}
public class Client
{
public Client()
{
GameAPI api = new GameAPI();
api.PlayerAdded += Api_PlayerAdded;
api.AddPlayer(new Player("Player2", "Clark"));
}
private void Api_PlayerAdded(object sender, PlayerAddedEventArgs e)
{
Console.WriteLine($"API PlayerAdded event has triggered. Arguments: e.Player.Name = {e.Player.Name}, e.Player.Pseudo = {e.Player.Pseudo}");
}
}
public class PlayerAddedEventArgs: EventArgs
{
public PlayerAddedEventArgs(Player player)
{
Player = player;
}
public Player Player { get; }
}
public class Player
{
public Player(string pseudo, string name)
{
Pseudo = pseudo;
Name = name;
}
public string Pseudo { get; }
public string Name { get; }
}
public class GameAPI
{
private List<Player> players = new List<Player>();
public event EventHandler<PlayerAddedEventArgs> PlayerAdded;
public void AddPlayer(Player player)
{
players.Add(player);
OnPlayerAdded(new PlayerAddedEventArgs(player));
}
protected virtual void OnPlayerAdded(PlayerAddedEventArgs e)
{
PlayerAdded?.Invoke(this, e);
}
}
The two main classes here are GameAPI and Client.
GameAPI class:
Keeps track of all added players in the private players list.
Provides an AddPlayer method allowing clients to add players.
Provides a PlayerAdded event to notify clients that a player has been added.
Client class:
Subscribes to the PlayerAdded event exposed by the GameAPI.
Calls AddPlayer method to add the new player.
AddPlayer method adds the player to the internal players list and calls OnPlayerAdded which notifies all subscribed clients about the new player. This notification causes the Api_PlayerAdded method in all subscribed instances of the Client class to be called. The added player will be accessible as the Player property in the e argument passed to this method.
Original answer:
I don't see any issues with your code. I modified the Api_JamesAdded method to make sure it works properly, so the full code looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
Client client = new Client();
}
}
public class Client
{
public Client()
{
GameAPI api = new GameAPI();
api.AddedPlayerEvent += Api_JamesAdded;
api.Do();
}
private void Api_JamesAdded(object sender, GameAPI.AddedPlayerEvents e)
{
Console.WriteLine($"Name: {e.Name}, Pseudo: {e.Pseudo}");
}
}
public class GameAPI
{
public event EventHandler<AddedPlayerEvents> AddedPlayerEvent;
List<AddedPlayerEvents> AddedPlayers = new List<AddedPlayerEvents>();
public GameAPI()
{
// some code to simulate generating some data
AddedPlayers.Add(new AddedPlayerEvents("Player1", "James"));
OnPlayerAdded(AddedPlayers.First(f => f.Pseudo == "Player1"));
AddedPlayers.Add(new AddedPlayerEvents("Player2", "Clark"));
OnPlayerAdded(AddedPlayers.First(f => f.Pseudo == "Player2"));
AddedPlayers.Add(new AddedPlayerEvents("Player3", "Steve"));
OnPlayerAdded(AddedPlayers.First(f => f.Pseudo == "Player3"));
}
public void Do()
{
// simulating code ...
//trigger event
if (AddedPlayers.Any(f => f.Name == "Clark")) /*value Clark should come from client using subsciber or something else*/
{
OnPlayerAdded(AddedPlayers.First(f => f.Name == "Clark"));
}
}
protected virtual void OnPlayerAdded(AddedPlayerEvents e)
{
EventHandler<AddedPlayerEvents> handler = AddedPlayerEvent;
if (handler != null)
{
handler(this, e);
}
}
public class AddedPlayerEvents
{
public string Pseudo { get; set; }
public string Name { get; set; }
public AddedPlayerEvents(string pseudo, string name)
{
Pseudo = pseudo;
Name = name;
}
}
}
This code prints:
Name: Clark, Pseudo: Player2
If this is not what you expected, please post the expected output.
I am learning how to do unit testing. I tried to search for how to do testing for a button click event but couldn't find an answer that I could understand.
How can I check if TextBlock_MouseDown event was raised and followed by reponse from PostMethod, which must not be null. My issue is, I can't find a way or don't know how to check TextBlock_MouseDown event using NUnit.
public partial class MainWindow : Window
{
public MainWindow(){
InitializeComponent();
}
public void TextBlock_MouseDown(object sender, MouseButtonEventArgs e){
//Check return value from PostMethod
string reponse = PostMethod("myurlhere");
}
public static String PostMethod(String val){
//Code
}
}
[TestFixture]
public class TestClass
{
[Test]
public void PostMethod_IsAlive_returnHello()
{
//ARRANGE
String url = "myurlhere";
//ACT
string response = MainWindow.PostMethod(url);
//ASSERT
Assert.AreEqual("\"Hello\"", response);
}
}
If you want to to test your UI, you should use a test library for UI-Testing.
For example FlaUI (https://github.com/Roemer/FlaUI).
NUnit is used to test your code behind. For example if you want to check if PostMethod() is returning a specific value.
If you only want to check the result of PostMethod(), outsource the method to another class and test it (MainWindow will now use OutsourcedClass.PostMethod() in its code behind).
outsourced class
public class OutsourcedClass
{
public string PostMethod(string url)
{
return url;
}
}
unit test
public class OutsourcedClassTest
{
private OutsourcedClass _Instance;
[SetUp]
public void Setup()
{
_Instance = new OutsourcedClass();
}
[Test]
public void PostMethodTest()
{
string url = "foo";
Assert.AreEqual(url, _Instance.PostMethod(url));
}
}
I am doing some unit tests with NUnit and NSubstiture.
I have this class:
public class Presenter
{
public Presenter()
{
}
private readonly IView _view;
public Presenter(IView view)
{
_view = view;
this._view.Loaded += OnLoaded;
}
private void OnLoaded()
{
_view.Render("Hello Word");
}
}
And I have this Interface:
public interface IView
{
event Action Loaded;
void Render(string text);
}
And I have already a unit test with the NSubstiture framework, like this:
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithMockingFramework()
{
var mockView = Substitute.For<IView>();
Presenter p = new Presenter(mockView);
mockView.Loaded += Raise.Event<Action>();
mockView.Received().Render(Arg.Is<string>(s => s.Contains("Hello World")));
}
But now I want for just testing purpose, write the same unit test , but then without the NSubstiture framework:
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework()
{
IView view;
Presenter MockingVIew = new Presenter(view);
}
But how to do this?
Thank you
I try it like this:
public class FakePresenter : IView
{
public event Action Loaded;
public void Render(string text)
{
}
}
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework()
{
//FakeMockingVIew = new Presenter(view);
FakePresenter fPresenter = new FakePresenter();
Presenter p = new Presenter(fPresenter);
fPresenter.Loaded += Raise.Event<Action>();
fPresenter.Received();
Assert.That(fPresenter, Is.EqualTo());
}
If you no longer want to use the mocking framework, nothing is stopping you from creating a class derived from IView yourself and using that as the dependency in the test
public class MyTestClass {
public class FakePresenter : IView {
public event Action Loaded = delegate { };
public void Render(string text) {
RenderedText = text;
}
public string RenderedText { get; private set; }
public void Load() {
Loaded();
}
}
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework() {
//Arrange
var fake = new FakePresenter();
var subject = new Presenter(fake);
var expected = "Hello Word";
//Act
fake.Load();
var actual = fake.RenderedText;
//Assert
Assert.AreEqual(expected, actual);
}
}
The above implementation of the dependency exposes a Load() method to raise the event for all subscribers and also a RenderedText property to capture the text passed into the Render method so that an assertion can be made based on the value.
When you used NSubstitute, you had to tell the mock view to raise an event. But since the IView interface doesn't allow you to trigger the event, only add an event listener, NSubstitute does a workaroud, by attaching a special event handler, it actually triggers an event (I'm not familiar with NSubstitute, but I assume this is what happens):
// Code here says "attact an event handler", but NSubstitute recognizes this
// special event handler and raises the event to the "real" hanlders instead
mockView.Loaded += Raise.Event<Action>();
So when you move away from NSubstitute, you need to actually trigger the event the "correct" way from the fake view class:
public class FakeView : IView
{
private string RenderedText { get; private set; }
public event Action Loaded;
public void Render(string text)
{
renderedText = text;
}
public void RaiseLoaded() {
if (Loaded != null) Loaded();
}
}
Now you can easily trigger the events from your test:
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework()
{
FakeView view = new FakeView();
Presenter p = new Presenter(fPresenter);
view.RaiseLoaded();
Assert.That(view.RenderedText, Is.EqualTo("Hello World"));
}
I'm building an email-monitoring framework that I'll be using for a handful of users, so I'm building a class library to wrap everything in. I'm instantiating the configuration (sender, subject, last-received, ...) in a static class. Therefore, I have something like this.
public static class MyConfig
{
public static int Sender { get; set; }
// and so on and so forth
public static void BuildMyConfig(string theSender, string theRecipient, ...)
{
Sender = theSender;
// yada yada yada...
}
}
public class Monitoring
{
public delegate void DoSomethingWithEmail(EmailContents theContents);
public void StartMonitoring() {
//When I get an email, I call the method
DoSomethingWithEmail(theEmailWeJustGot);
}
}
Obviously, what we do with the email will be something completely different in each case. What I'm trying to is instantiate that delegate. Where would I do that? The MyConfig class and then invoke it from there as a static method? The instance of the Monitoring class?
An application would look like...
public class SpecificMonitor
{
Monitoring.BuildMyConfig("foo#bar.com", "bar#foo.com", ...);
Monitoring m = new Monitoring();
m.StartMonitoring();
//But where do I build the delegate method???
}
I've gotten compiling errors with every option I've tried so far. I've also tried overriding a method instead of using a delegate, using interfaces... but I think delegation is where it's at.
Thanks in advance!
Consistent with the rest of your design (although I do not necessarily agree that the design is great) you could allow for the callback to be set in the configuration class
public static class MyConfig
{
public static string Sender { get; set; }
public static DoSomethingWithEmail EmailReceivedCallback { get; set; }
public static void BuildMyConfig(string theSender, string theRecipient,
DoSomethingWithEmail callback)
{
Sender = theSender;
EmailReceivedCallback = callback;
}
}
// Make sure you bring the delegate outside of the Monitoring class!
public delegate void DoSomethingWithEmail(string theContents);
When an incoming email is acknowledged by your application you can now pass the email to the callback assigned to the configuration class
public class Monitoring
{
public void StartMonitoring()
{
const string receivedEmail = "New Answer on your SO Question!";
//Invoke the callback assigned to the config class
MyConfig.EmailReceivedCallback(receivedEmail);
}
}
Here is an example of usage
static void Main()
{
MyConfig.BuildMyConfig("...", "...", HandleEmail);
var monitoring = new Monitoring();
monitoring.StartMonitoring();
}
static void HandleEmail(string thecontents)
{
// Sample implementation
Console.WriteLine("Received Email: {0}",thecontents);
}
Define the constructor so that when people instantiate a Monitoring object, they must define the delegate:
public class Monitoring
{
public delegate void DoSomethingWithEmail(EmailContents theContents);
public Monitoring(Delegate DoSomethingWithEmail)
{
this.DoSomethingWithEmail = DoSomethingWithEmail;
}
public void StartMonitoring() {
//When I get an email, I call the method
DoSomethingWithEmail(theEmailWeJustGot);
}
}
Then pass in the delegate you want when you instantiate each Monitoring:
Monitoring m = new Monitoring(delegate(EmailContents theContents)
{
/* Do stuff with theContents here */
});
m.StartMonitoring();
Im making a program what connects to multiple 3th party systems. The connect with different formats so i created multiple classes to deal with them. I have now three 4 classes.
The MainForm is the first class. This is the basic windows form class with the user interface.
SDKCommunication is the second class.
VMS (this class handles the events given of by the 2th party system and activates methods on SDK COmmunication)
Events
Events Class
public class Events
{
public event EventHandler LoginStateChanged;
private bool loginstate;
public bool LogInState
{
get { return this.loginstate; }
set
{
this.loginstate = value;
if (this.LoginStateChanged != null)
this.LoginStateChanged(this, new EventArgs());
}
}
}
part of SDKCommunicatie class
Events events = new Events();
public void onLogon(string username, string directory, string system)
{
events.LogInState = false;
}
MainForm Class
SDKCommunicatie sdkcommunicatie = new SDKCommunicatie();
Events events = new Events();
public MainForm()
{
InitializeComponent();
events.LoginStateChanged += new EventHandler(events_LoginStateChanged);
}
void events_LoginStateChanged(object sender, EventArgs e)
{
log.Info("EventFired loginstateChanged");
}
When the LogInState Changes in the SDKCommunicatie class. There needs to be an event fired in the MainForm class. But sadly that doesn't work.
But when I change the loginstate in the mainform(with a buttonclick)(see code below) the event is fired. But that is not the intention i would like to have.
private void button1_Click(object sender, EventArgs e)
{
events.LogInState = true;
}
If my question isn't clear enough, please let me know.
VMS class Added as reply to #Astef
class VMS {
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(MainForm));
GxUIProxyVB m_UIProxy = new GxUIProxyVB();
public string username2;
public string directory2;
public string Status;
public void initOmni()
{
m_UIProxy.CreateInstance();
m_UIProxy.OnLogon += new _IGxUIProxyVBEvents_OnLogonEventHandler(m_UIProxy_OnLogon);
m_UIProxy.OnLogoff += new _IGxUIProxyVBEvents_OnLogoffEventHandler(m_UIProxy_OnLogoff);
m_UIProxy.OnError += new _IGxUIProxyVBEvents_OnErrorEventHandler(m_UIProxy_OnError);
m_UIProxy.OnAlarmStatusEx2 += new _IGxUIProxyVBEvents_OnAlarmStatusEx2EventHandler(m_UIProxy_OnAlarmStatusEx2);
}
public void login(string username, string password, string directory)
{
username2 = username;
directory2 = directory;
initOmni();
m_UIProxy.LogOn(directory, username, password,false);
}
public void logOff()
{
m_UIProxy.LogOff();
}
void m_UIProxy_OnLogon()
{
SDKCommunicatie sdkcommunicatie = new SDKCommunicatie();
sdkcommunicatie.onLogon(username2, directory2, "Genetec Omnicast");
}
I have fixed this with deleting the following:
SDKCommunicatie sdkcommunicatie = new SDKCommunicatie();
And adding the following in the base of VMS:
SDKCommunicatie sdkcommunicatie;
But now i got a new error in the mainform when i tried to call a class in SDKCommunicatie
connectedStatus = sdkcommunicatie.connectedStatus();
I got the following error:
NullReferenceException was unhandled
You are not using the same instance of the Events class, and that's why on button click you catch LoginStateChanged. You should inject the same instance of Events class to SDKCommunicatie class, then you'll be able to listen to event changes.
Edit:
Jeremy Todd and I were both writing at the same time.
Events in your SDKCommunicatie are not fired because you've created an individual instance of class Events for it. That is not the instance you have placed on the MainForm.
Inject the right instance (pass a reference) to SDKCommunicatie from MainForm through constructor, property or somehow else. For example:
MainForm:
SDKCommunicatie sdkcommunicatie;
Events events = new Events();
public MainForm()
{
InitializeComponent();
events.LoginStateChanged += new EventHandler(events_LoginStateChanged);
sdkcommunicatie = new SDKCommunicatie(events);
}
void events_LoginStateChanged(object sender, EventArgs e)
{
log.Info("EventFired loginstateChanged");
}
SDKCommunicatie:
Events events;
public SDKCommunicatie(Envents eventsInstance)
{
events = eventsInstance;
}
public void onLogon(string username, string directory, string system)
{
events.LogInState = false;
}
Your SDKCommunication class and your MainForm class each have their own separate instance of Events, so any events you trigger from one won't be visible from the other -- they're being raised on an entirely different object.
What you need is a single instance of the Events class that both SDKCommunication and MainForm can share -- that way they'll both be seeing the same thing. There are several different approaches you could take for this. Depending on what it needs to do, one very simple possibility might be to make Events a static class, and then the events would be visible everywhere without needing to create any instances.
I have solved the riddle.
When i need a method is a class i can call the method directly like this:
public class MainForm : Form
{
SDKCommunication sdkcommunication = new SDKCommunication();
public MainForm()
{
}
private void Button1_Click(oject sender, EventArgs e)
{
sdkcommunication.method("Test")
}
}
This is pretty straightforward. Look here the receiverclass:
public class SDKCommunication
{
method(string word)
{
//do something with word
}
}
The biggest problem is calling the class with the form(the original class). I have solved this with a eventhandler.
class CustomEventHandler1 : EventArgs
{
public CustomEventHandler1(string u, string d)
{
msgu = u;
msgd = d;
}
private string msgu;
private string msgd;
public string Username
{
get { return msgu; }
}
public string Directory
{
get { return msgd; }
}
}
Then the SDKCOmmunication class should look like this:
class SDKCommunication
{
public event EventHandler<CustomEventHandler1> RaiseCustomEventHandler1;
protected virtual void OnRaiseCustomEventHandler1(CustomEventHandler1 e)
{
EventHandler<CustomEventHandler1> handler = RaiseCustomEventHandler1;
if (handler != null)
{
handler(this,e);
}
}
//Custom Method that is called somewhere
internal void custommethod()
{
OnRaiseCustomEventHandler1(new CustomEventHandler1("johnsmith", "localhost");
}
}
Then in the mainform class:
public class MainForm : Form
{
public MainForm()
{
sdkcommunication.RaiseCustomEventHandler1 += new EventHandler<CustomEventHandler1>(sdkcommunication_RaiseCustomEventHandler1);
}
void sdkcommunication_RaiseCustomEventHandler1(object sender, CustomEventHandler1 e)
{
//Do something.
}
}
The information sended with the event you can get with e.Username and e.Directory. In this example they are strings where e.Username = johnsmith and e.Directory = localhost.
I hope somebody can use this information for their own code.