Im in the process of writing a test for a small application that follows the MVP pattern.
Technically, I know I should have written the test before the code, but I needed to knock up a demo app quick smart and so im now going back to the test before moving on to the real development.
In short I am attempting to test the presenter, however I cannot even get an empty test to run due to an Internal.ExpectationException.
The exception is raised on a unexpected invocation of an event assignation.
Here is the presenter class,
public LBCPresenter(IView view, IModel model)
{
m_model = model;
m_model.BatteryModifiedEvent += new EventHandler(m_model_BatteryModifiedEvent);
}
Model Interface
public interface IModel
{
event EventHandler BatteryModifiedEvent;
}
And here is the test class, I can't see what im missing, ive told NMock to expect the event...
[TestFixture]
public class MVP_PresenterTester
{
private Mockery mocks;
private IView _mockView;
private IViewObserver _Presenter;
private IModel _mockModel;
[SetUp]
public void SetUp()
{
mocks = new Mockery();
_mockView = mocks.NewMock<IView>();
_mockModel = mocks.NewMock<IModel>();
_Presenter = new LBCPresenter(_mockView, _mockModel);
}
[Test]
public void TestClosingFormWhenNotDirty()
{
Expect.Once.On(_mockModel).EventAdd("BatteryModifiedEvent", NMock2.Is.Anything);
//makes no difference if following line is commented out or not
//mocks.VerifyAllExpectationsHaveBeenMet();
}
}
Every time I run the test I get the same expectation Exception.
Any ideas?
I think its a timing issue - you are calling the presenter constructor in the test Setup - this means the event add is happening before your test sets up the EventAdd expectation.
If you move your call to the presenter constructor below the EventAdd expection it should work
Related
namespace Game.SoccerGame
[TestFixture]
public class Score_is_0_0 : SoccerGame
{
[SetUp]
public void SetUp()
{
GivenTheScoreIs(0,0);
}
[TearDown]
public void CleanUp()
{
}
[Test]
public void When_Team1_Scores()
{
WhenTeam1Scores();
Assert.That(ScoreOutput, Is.EqualTo("1:0"));
}
[Test]
public void When_Team2_Scores()
{
WhenTeam2Scores();
Assert.That(ScoreOutput, Is.EqualTo("0:1"));
}
}
Expected:
When_Team1_Scores() = 1:0
When_Team1_Scores() = 0:1
When I run the tests individually they work as expected.
The issue I am having is when I run the tests in the class all at the same time. When I do this the results are:
When_Team1_Scores() = 1:0
When_Team1_Scores() = 1:1
the ScoreOutput keeps its state after the first test and thus my second test fails
What is the best approach the kill the state in-between tests in the TearDown?
I have the object below in a separate class SoccerGame that I inherit that controls the score state
public abstract class SoccerGame : IDisposable
private SetScore currentScore = new SetScore();
protected string ScoreOutput => currentScore.ToString();
public void Dispose()
{
}
I tried to use IDisposable but it doesn't see to work or I am implementing it wrong?
When using NUnit, a single instance of the fixture is created and used for all the tests in the fixture. Because of that, any state that needs to be initialized should be taken care of in the SetUp method, which runs before each test.
You don't show the code for your method GivenTheScoreIs but it sounds like it's supposed to initialize the score. To ensure that it is working correctly, add a test that verifies the score is set (0:0).
The above should work. However, I recommend going a step further and not inheriting from SoccerGame, which is presumably the class you are testing. While inheriting a test in this way is occasionally useful, it isn't the normal or the cleanest way to do it. It's better to separate your system under test from the tests themselves.
To do that, I suggest you instantiate a new SoccerGame for each test, doing so in the SetUp method. That will eliminate any possibility of state carrying over from one test to another since each test will use a new SoccerGame.
I'm attempting to create a WPF MVVM View Model that has a dependency injected System.Timing.Timer, and wish to test the view model with Moq.
I wrote a thin wrapper around the Timer class that has a interface ITimer, but am unsure of the best way to really test the timer's contribution to the class. Is there a good way to 'force' a mock elapsed event? Does somebody else have a better technique?
You should test your code in isolation. Otherwise you don't know whether your code behaves as expected, or there is some side-effect in external dependency. Thus creating mockable wrappers for external resources (configuration files, timers, etc) is the only way you can separate your SUT from external code.
You could use a framework like Moq to trigger the event. You could also create a FakeTimer like so:
public class FakeTimer : IMyTimer
{
private event ElapsedEventHandler elaspedHandler;
private bool _enabled;
public void Dispose() => throw new NotImplementedException();
public FakeTimer(ElapsedEventHandler elapsedHandlerWhenTimeFinished, bool startImmediately)
{
this.elaspedHandler = elapsedHandlerWhenTimeFinished;
_enabled = startImmediately;
}
public void Start() => _enabled = true;
public void Stop() => _enabled = false;
public void Reset() => _enabled = true;
internal void TimeElapsed()
{
if (this._enabled)
elaspedHandler.Invoke(this, new EventArgs() as ElapsedEventArgs);
}
}
Where TimeElapsed() is what you would call in your unit tests to indicate that the time has passed.
It will then call off to the event associated with it.
In this example below, MyCallBackMethod would be called on fakeTimer.TimeElapsed()
var fakeTimer = new FakeTimer(350, MyCallBackMethod, false)
Im trying to test a method which composes a collection of controls. It calls two methods:
Copies the original collection.
Sorts the new collection.
Ideally id like to be able to pass in a collection and test to see thats it sorts it correctly. Id also like to verify that method 1) is called twice, see below attempt based on the following:
Example using RhinoMock
The following test is producing errors when i try to create an instance of MainPresenter. General jist of the errors are "Can not convert from Moq.Mock to "FrazerMann.CsvImporter.UserInterface.IMainForm. + a similar one for IFileDialog.
[Test]
public void ComposeCollectionOfControls_CallSequence_4Calls()
{
var main = new Mock<IMainForm>();
var dialog = new Mock<IFileDialog>();
var temp = new Mock<IMainPresenter>();
temp.Setup(s => s.PopulateLists<Control>(It.IsAny<TableLayoutPanel>(), It.IsAny<List<Control>>()));
var testObject = new MainPresenter(main.Object, dialog.Object);
testObject.ComposeCollectionOfControls(It.IsAny<object>(), It.IsAny<EventArgs>());
temp.Verify(v => v.PopulateLists<Control>(It.IsAny<TableLayoutPanel>(), It.IsAny<List<Control>>()), Times.Once());
}
I would like to test the ComposeCollectionOfControls to ensure PopulateList() is called twice.
public interface IMainPresenter
{
void PopulateLists<T>(TableLayoutPanel userInputs, List<T> container) where T : Control;
int SortList<T>(T control1, T control2) where T : Control;
}
public class MainPresenter:IMainPresenter
{
UserInputEntity inputs;
IFileDialog _dialog;
IMainForm _view;
public MainPresenter(IMainForm view, IFileDialog dialog)
{
_view = view;
_dialog = dialog;
view.ComposeCollectionOfControls += ComposeCollectionOfControls;
view.SelectCsvFilePath += SelectCsvFilePath;
view.SelectErrorLogFilePath += SelectErrorLogFilePath;
view.DataVerification += DataVerification;
}
public void ComposeCollectionOfControls(object sender, EventArgs e)
{
PopulateLists<TextBox>(_view.ColumnNameCtrls, _view.SortedColumnNameCtrls);
_view.SortedColumnNameCtrls.Sort(SortList<TextBox>);
PopulateLists<ComboBox>(_view.ColumnDataTypeCtrls, _view.SortedColumnDataTypeCtrls);
_view.SortedColumnDataTypeCtrls.Sort(SortList<ComboBox>);
}
}
Could someone please give me some pointers as to how this should be done?
The error you are seeing is because your are passing the mock class itself (which is of type Moq.Mock) rather than the mocked object that Moq creates for you.
Instead of:
var testObject = new MainPresenter(main, dialog);
you need:
var testObject = new MainPresenter(main.Object, dialog.Object);
As an aside, it is usually considered bad practice to explicitly verify things like the number of calls made on a particular method. This leads to a tight coupling between your tests and a particular implementation, and consequently brittle tests.
By testing how many times you call a method you will often find a test failing after you refactor some code when the end result of the code is still correct.
It is much better to test the final state of the objects involved, and make your tests ignorant of how that state was reached.
I'm using a boilerplate implementation of Model-View-Presenter in an ASP.NET WebForms application. My View has two events of consequence, one that signals that the user has filled out enough fields on the domain model to initiate a duplication check, and the other is a regular Save event. My pseudo code looks like this:
public class ItemNewPresenter : PresenterBase<IItemNewView>
{
public IItemService Service { get; private set; }
public IItemNewView View { get; private set; }
public ItemNewPresenter(IItemService service, IItemNewView view)
{
Service = service;
View = view;
View.OnSave += DoItemSave;
View.OnItemIsDuplicateCheck+= DoItemIsDuplicateCheck;
}
private void DoItemIsDuplicateCheck(object sender, CheckItemDuplicateEventArgs e)
{
CheckForItemDuplication(e.Item);
}
private void CheckForItemDuplication(Item item){
if (Service.IsDuplicateItem(item))
{
View.RedirectWithNotification(BuildItemUrl(item), "This item already exists");
}
}
private void DoItemSave(object sender, SaveItemEventArgs e)
{
DoItemIsDuplicateCheck(this, e.ToItemDuplicateEventArgs());
Service.Save(e.Item);
}
}
Here's my test for ensuring that my presenter behaves properly when OnItemIsDuplicateCheck is raised from the view:
[Test]
public void presenter_checking_for_existing_item_should_call_redirect_if_found()
{
var service = new Mock<IItemService>();
var view = new Mock<IItemNewView>();
var presenter = new ItemNewPresenter (service.Object, view.Object);
var onCheckExistingHandler = view.CreateEventHandler <CheckItemDuplicateEventArgs>();
view.Object.OnExistingDenominatorCheck += onCheckExistingHandler;
var eventArgs = new CheckItemDuplicateEventArgs();
service.Setup(s => s.IsDuplicate(It.Is<CheckItemDuplicateEventArgs>(c => c.Equals(eventArgs)))).Returns(true);
onCheckExistingHandler.Raise(eventArgs);
view.Verify(v => v.RedirectWithNotification(It.IsAny<String>(), It.IsAny<string>()), Times.Once());
service.Verify();
}
For consistency, I would like to have the same duplicate check fired when the View raises the OnSave event. My question is around how I am supposed to write my test when one of the methods I want to verify (CheckForItemDuplication) is declared on the class under test. The alternative to verifying the method invocation on the SUT (bad) would be to write my save test with lots of duplicated code (setup and assertion of all my mocks would be copied from the above test) and it also makes the unit test less focused.
[Test]
public void presenter_saving_item_should_check_for_dupe_and_save_if_not_one() {
//duplicate mocks/setups/asserts from duplicate check fixture
//additional mocks/setups/asserts to test save logic
}
I think TDD would suggest pulling this private method out into a separate class that collaborates with my Presenter and would be injected via DI. But adding another dependency to my Presenter for functionality that doesn't seem worthy of being a freestanding abstraction *and*represents an internal implementation detail of my Presenter seems...well...crazy. Am I way off base here? There must be some design pattern or refactoring I can apply that would avoid the need to turn a private method into a dependency.
What I have done sometimes, when confronted with this dilemma, is to extract the function, make an internal constructor with the object as argument, AND a public constructor without. The public ctor is forwarded to the internal with a new object such as:
public class ClassThatUseInjection
{
private readonly SomeClass _injectedClass;
public ClassThatUseInjection(): this(new SomeClass()) {}
internal ClassThatUseInjection(SomeClass injectedClass)
{
_injectedClass = injectedClass;
}
}
public class SomeClass
{
public object SomeProperty { get; set; }
}
Thus, you can use the empty constructor from outside, and the other constructor for when you want to inject a stubbed argument for testpurposes. As long as the empty constructor only forwards the call without any logic of its own, you can still test it, like it has only one constructor.
I would go with testing the class as is by adding the duplicate setup code. Once that test is passing and you are confident all test cases are covered you can then refactor your test code to remove duplication.
You can move the dependencies (service and view) to private fields, then add a method to create the SUT:
private Mock<IItemService> _service;
private Mock<IItemNewView> _view;
private PresenterBase<IItemNewView> CreateSUT()
{
_service = new Mock<IItemService>();
_view = new Mock<IItemNewView>();
return new ItemNewPresenter (service.Object, view.Object);
}
(I think most people would prefer to initialize the Mock objects in the Setup method.)
Call the CreateSUT from your tests and now there is a little less duplication. Then you may want to add private method(s) for creating the event handler / raising the event as long as it is something that is being done the same or similar in more than one tests case.
Having this CreateSUT method cuts down on the amount of test code that is calling your constructor making it easier in the future if you were to add / remove / change dependencies. If you treat your test code like any other code and use the DRY principle when you see duplication it can result in more explicit, easier to read, maintainable test code. Dealing with very similar setup and test context is a common issue with unit testing and should not always change how the class being tested is/was designed.
I'll be interested if there are better answers, as I encounter this all the time.
The alternative to verifying the method invocation on the SUT (bad) would be to write my save test with lots of duplicated code (setup and assertion of all my mocks would be copied from the above test) and it also makes the unit test less focused.
I'm not sure why you feel it makes the test less focused, but in your shoes I would do exactly what it sounds like you don't want to do--have duplicated setup code to test isolated cases for the SUT. You are testing the external behavior of the SUT with the test you supplied, which seems exactly right to me.
I am personally not a fan of exposing more than is necessary from a class and/or making behavior that should be the responsibility of the SUT into a dependency just to facilitate testing. The "natural boundry" of the class's responsibility should not be violated just because you want to test it.
It is easier to unit-test the calculation of the url than to unit-test that redirection has occured.
If i understood you corretly you want to test that the mvp-s CheckForItemDuplication() redirects to a certain url by raising
the view-mock-s OnItemIsDuplicateCheck event.
private void CheckForItemDuplication(Item item)
{
if (Service.IsDuplicateItem(item))
{
View.RedirectWithNotification(BuildItemUrl(item),
"This item already exists");
}
}
In my opinion you are doing to much.
What if you rewrite your code as
internal protected GetErrorUrlForItem(Item item)
{
if (Service.IsDuplicateItem(item))
{
return BuildItemUrl(item,
"This item already exists");
}
return null;
}
private void CheckForItemDuplication(Item item)
{
var result = GetErrorUrlForItem(item);
if (result != null)
{
View.RedirectWithNotification(result);
}
}
In the unittest just test the internal method GetErrorUrlForItem(). You have to use the InternalsVisibleTo attribute to allow accessing the internal method.
Ok, I've got a strange problem. I am testing a usercontrol and have code like this:
[TestFixture]
public myTestClass : UserControl
{
MyControl m_Control;
[Test]
public void TestMyControl()
{
m_Control = new MyControl();
this.Controls.Add(m_Control);
Assert.That(/*SomethingOrOther*/)
}
}
This works fine, but when I change it to:
[TestFixture]
public myTestClass : UserControl
{
MyControl m_Control;
[Setup]
public void Setup()
{
m_Control = new MyControl();
this.Controls.Add(m_Control);
}
[TearDown]
public void TearDown()
{
this.Controls.Clear();
}
[Test]
public void TestMyControl()
{
Assert.That(/*SomethingOrOther*/);
}
}
I get an Object Reference Not Set To An Instance of an Object. I even output to the console to ensure that the setup/teardown were running at the correct times, and they were... but still it isn't newing up the usercontrols.
edit> The exact code is:
[TestFixture]
public class MoneyBoxTests : UserControl
{
private MoneyBox m_MoneyBox;
private TextBox m_TextBox;
#region "Setup/TearDown"
[SetUp]
public void Setup()
{
MoneyBox m_MoneyBox = new MoneyBox();
TextBox m_TextBox = new TextBox();
this.Controls.Add(m_MoneyBox);
this.Controls.Add(m_TextBox);
}
[TearDown]
public void TearDown()
{
this.Controls.Clear();
}
#endregion
[Test]
public void AmountConvertsToDollarsOnLeave()
{
m_MoneyBox.Focus();
m_MoneyBox.Text = "100";
m_TextBox.Focus();
Assert.That(m_MoneyBox.Text, Is.EqualTo("$100.00"), "Text isn't $100.00");
}
[Test]
public void AmountStaysANumberAfterConvertToDollars()
{
m_MoneyBox.Focus();
m_MoneyBox.Text = "100";
m_TextBox.Focus();
Assert.That(m_MoneyBox.Amount, Is.EqualTo(100), "Amount isn't 100");
}
}
I get the exception(s) at the respective m_MoneyBox.Focus() calls.
Solved - See Joseph's comments
I created a test case with exactly the same layout you presented here, but with a TextBox instead of a MyControl. I also added a constructor and a deconstructor and outputted all the various stages to the console to see the sequence of events. However, I never got an object reference exception.
In case you are interested, the sequence was [constructor called], [setup called], [test called], [tear down called]. The deconstruction never output anything to the screen for some reason.
My original thought was that the Controls property on myTestClass would not be initialized, but on my test it was, so I think it has something to do with your MyControl construction.
edit> I added the focus on my TextBox in my unit test as well but still no exception. Does your MoneyBox have any event handling going on behind the scenes during the Focus? That might be your culprit.
You haven't said where you're getting the exception, which would help - what does the stack trace look like?
It's very odd (IME) to derive from UserControl when you create a test fixture. Aside from anything else, I don't know that NUnit is going to call Dispose for you at any appropriate point... what's the purpose of it here? Can you not make your tests run with a "plain" test fixture?
I had exactly the same issue, so my apologies for answer to this old post.
The problem in your code (and mine) is that you are creating 2 different instances for MoneyBox and 2 more for TextBox. So, the initial assignation inside Setup, is valid only for Setup method and out_of_scope in the test methods.
Inside the Setup method you should use:
m_MoneyBox = new MoneyBox(); //GOOD
m_TextBox = new TextBox(); //GOOD
instead of
MoneyBox m_MoneyBox = new MoneyBox(); //BAD
TextBox m_TextBox = new TextBox(); //BAD
Just for anyone that could need it again