Writing unit test without mocking framework - c#

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"));
}

Related

NUnit Check if button was click

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));
}
}

How to test if no event was invoked

I am new to UnitTests and therefore to Xunit. I have wrote some tests, but I am stuck with the testing of events.
Is it possible to test that no event was invoked with xunit?
I used this example for preparing my tests.
The first test works fine. For the second test, I expected something like 'Assert.RaisesNoEvent'; However, that method is not available.
Is there another way to test that no event was invoked?
Code Sample
Class where Event is Raised when Property2 is Set
public class Class
{
private int _property2;
public event EventHandler RelevantPropertyChanged;
public void OnRelevantPropertyChanged(EventArgs args){
RelevantPropertyChanged?.Invoke(this, args);
}
public int Property1 { get; set; }
public int Property2 {
get { return _property2; }
set {
OnRelevantPropertyChanged(new EventArgs());
_property2 = value;
}
}
}
TestClass defines unit tests for Class
public class TestClass
{
[Fact]
public void ChangeProperty2_RaisesEvent()
{
var cl = new Class();
var args = new EventArgs();
var evt = Assert.RaisesAny<EventArgs>(
h => cl.RelevantPropertyChanged += h,
h => cl.RelevantPropertyChanged -= h,
() => cl.Property2 = 5);
Assert.NotNull(evt);
Assert.Equal(cl, evt.Sender);
Assert.Equal(args, evt.Arguments);
}
[Fact]
public void ChangeProperty1_RaisesNoEvent()
{
var cl = new Class();
Action code = () => cl.Property1 = 5;
Assert.RaisesNoEvent(code); //this is what I want to do
}
}
You can check that the event was not raised by checking that the EventHandler was not invoked:
[Fact]
public void ChangeProperty1_RaisesNoEvent()
{
var instance = new Class();
bool isInvoked = false;
instance.RelevantPropertyChanged += (s, e) => isInvoked = true;
Assert.False(isInvoked);
instance.Property1 = 5;
Assert.False(isInvoked);
}
This technique works with any unit testing framework.

Trigger event called by an another class

I want to triggered my event when my UI call my class, life this :
In my UI i call my class ScanClass with a string parameter
ScanMessage scn = new ScanMessage(message);
In my class ScanMessage i made this :
public class ScanMessage
{
public delegate void OnScanMessageReceived(string message);
public ScanMessage()
{
}
public ScanMessage(string message)
{
MessageReceived(message);
}
public event OnScanMessageReceived MessageReceived;
}
And i made this in my FirstViewModel
public FirstViewModel()
{
var scanMessage = new ScanMessage();
scanMessage.MessageReceived += ScanMessage_MessageReceived;
}
private void ScanMessage_MessageReceived(string message)
{
//Do something
}
Well, if i post here, it's because i have a problem and i can't fix it without help !
Thank.
The reason is the instance of ScanMessage is different. UI class has different instance and VM has different instance. Hence raising event on one instance is not being heard in other one.
If all your ScanMessage needs to do is to broadcast event, you can have its singleton instance
public class ScanMessage
{
public delegate void OnScanMessageReceived(string message);
private static ScanMessage _scanMessage = new ScanMessage();
private ScanMessage()
{
}
public static ScanMessage Instance
{
get
{
return _scanMessage;
}
}
public void BroadCastMessage(string message)
{
MessageReceived(message);
}
public event OnScanMessageReceived MessageReceived;
}
And then from UI you can call like
ScanMessage.Instance.BroadCastMessage(message);
and in your VM you can
public FirstViewModel()
{
ScanMessage.Instance.MessageReceived += ScanMessage_MessageReceived;
}
private void ScanMessage_MessageReceived(string message)
{
//Do something
}

Mocking system events using MOQ

Is there a way to mock system events in C# such as SystemEvents.PowerModeChanged and artificially raise them in a MOQ setup?
A litte bit late, but here is an example for the implementation with an interface in front of SystemEvent Matt mentioned:
Interface:
public interface ISystemEvents
{
event PowerModeChangedEventHandler PowerModeChanged;
}
Adapter class:
public class SystemEventsAdapter : ISystemEvents
{
public event PowerModeChangedEventHandler PowerModeChanged;
}
Your registration on the event:
public class TestClass {
private readonly ITestService _testService;
public TestClass(ISystemEvents systemEvents, ITestService testService) {
_testService = testService;
systemEvents.PowerModeChanged += OnPowerModeChanged;
}
private void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
if (e.Mode == PowerModes.Resume)
{
_testService.DoStuff();
}
}
}
Test:
[TestFixture]
public class TestClassTests
{
private TestClass _cut;
private Mock<ISystemEvents> _systemEventsMock;
private Mock<ITestService> _testServiceMock;
[SetUp]
public void SetUp()
{
_systemEventsMock = new Mock<ISystemEvents>();
_testServiceMock = new Mock<ITestService>();
_cut = new TestClass(
_systemEventsMock.Object,
_testServiceMock.Object
);
}
[TestFixture]
public class OnPowerModeChanged : TestClassTests
{
[Test]
public void When_PowerMode_Resume_Should_Call_TestService_DoStuff()
{
_systemEventsMock.Raise(m => m.PowerModeChanged += null, new PowerModeChangedEventArgs(PowerModes.Resume));
_testServiceMock.Verify(m => m.DoStuff(), Times.Once);
}
}
}
No, not directly.
I see two ways to achieve this :
By Implementing an interface in front of the systemEvent
By using a detouring framework such as Moles Framework or the Microsoft Fakes

Raising an event from a mocked object using Rhino

I have a problem with raising an event on a mocked object. I am using Rhino Mocks 3.4. I have studied similar questions, but failed to reproduce any of the suggested solutions.
I have a class -- Foo -- which have a private method, that is only accessed by event invokation by an injected interface -- IBar.
How do I raise the event IBar.BarEvent, from a RhinoMock object, so I can Test the method in Foo?
Here is my code:
[TestFixture]
public sealed class TestEventRaisingFromRhinoMocks
{
[Test]
public void Test()
{
MockRepository mockRepository = new MockRepository();
IBar bar = mockRepository.Stub<IBar>();
mockRepository.ReplayAll();
Foo foo = new Foo(bar);
//What to do, if I want invoke bar.BarEvent with value =123??
Assert.That(foo.BarValue, Is.EqualTo(123));
}
}
public class Foo
{
private readonly IBar _bar;
private int _barValue;
public Foo(IBar bar)
{
_bar = bar;
_bar.BarEvent += BarHandling;
}
public int BarValue
{
get { return _barValue; }
}
private void BarHandling(object sender, BarEventArgs args)
{
//Eventhandling here: How do I get here with a Rhino Mock object?
_barValue = args.BarValue;
}
}
public interface IBar
{
event EventHandler<BarEventArgs> BarEvent;
}
public class BarEventArgs:EventArgs
{
public BarEventArgs(int barValue)
{
BarValue = barValue;
}
public int BarValue { get; set; }
}
Something like this I think:
bar.Raise(x => x.BarEvent += null, this, EventArgs.Empty);
http://ayende.com/wiki/Rhino+Mocks+3.5.ashx#Howtoraiseevents
You need an IEventRaiser, which you can get via
bar.BarEvent += null;
var eventRaiser = LastCall.IgnoreArguments().GetEventRaiser();
Then, when you want to raise the event, you can call eventRaiser.Raise with the required arguments, e.g. sender and event args (depends on your event handler definition).
(Edit: this is based on Rhino.Mocks 3.1!)

Categories

Resources