Writing NUnit Test Cases for method - c#

i am new for Nunit.please help for write a test case.
this is my class
public CommandModule(ICommandFetcher fetcher,ICommandBus commandBus)
{
//Get["/"] = p =>
//{z
// return Response.AsText((string)Request.Form.Username);
//};
Post["/"] = parameters =>
{
var commandRequest = this.Bind<MessageEnvelope>();
var command = fetcher.FetchFrom(commandRequest);
commandBus.Send((ICommand)command, commandRequest.MetaData);
return HttpStatusCode.OK;
};
}
}
and i want to test for check this method
commandBus.Send((ICommand)command, commandRequest.MetaData);
thank you!
i try it following way
[Test]
public void whern_reseiving_command_it_sent_to_the_command_bus()
{
var rCommand = new DummyCommand() { SomeProp = 2 };
var serializedCommand = JsonConvert.SerializeObject(rCommand);
var envelope = new MessageEnvelope() { MetaData = new MetaData() { MessageType = "DummyCommand", MessageTypeVersion = 1 }, MessageData = serializedCommand };
var fakeCommand = A.Fake<ICommandBus>();
var browser = new Browser(with =>
{
with.Module<CommandModule>();
with.Dependency<ICommandBus>(fakeCommand);
});
var result = browser.Post("/", with =>
{
with.HttpRequest();
with.JsonBody(envelope);
});
A.CallTo(() => fakeCommand.Send(rCommand,envelope.MetaData)).MustHaveHappened();
but A.CallTo(() => fakeCommand.Send(rCommand,envelope.MetaData)).MustHaveHappened();
it has some kind of error in rcommand value

It sounds like you are looking to explicitly test that ICommandBus.Send is called when your code is executed.
One approach is to mock the ICommandBus dependency. That is, insert a mock object implementing ICommandBus that is able to detect whether that method is called with the right parameter values.
If you take this approach, you would normally do this using a mocking framework (e.g. Moq, or RhinoMocks).
To explain how you would use a mock for this briefly, I will show how you can do this by by explicitly implementing a mock object object yourself that records method calls, and testing them afterwards.
E.g.
MockCommandBus : ICommandBus
{
ICommand PassedCommand { get; set; }
MetaData PassedMetaData { get; set; }
public void Send(ICommand command, MetaData metaData)
{
this.PassedCommand = command;
this.PassedMetaData = metaData;
}
}
Then your test case will look like this:
[TestCase]
public void PostSendsCommandOnBus()
{
// ARRANGE
var mockCommandBus = new MockCommandBus();
ICommand expectedCommand = <whatever you expect>;
MetaData expectedMetaData = <whatever you expect>;
// Code to construct your CommandModule with mockCommandBus.
// ACT
// Code to invoke the method being tested.
// ASSERT
Assert.AreEqual(expectedCommand, mockCommandBus.PassedCommand);
Assert.AreEqual(expectedMetaData , mockCommandBus.PassedMetaData );
}
Caveat:
Note that this is only one approach to unit testing that happens to fit exactly what you are asking for here. Excessive use of mocks to test explicit interaction with dependencies at a low level can lead to the development of very brittle test suites that are testing an underlying implementation rather than behaviour of a system.

Related

Testing of even easy behaviour leads to a jungle of testing functions

Until today I had a hard time with unit testing. For this reason I just started to read a book "The art of Unit Testing".
The author states that each "unit of work" has entry and exit points and that there should be a unit test for each exit point.
An "exit point" could be:
A return value of a function (also an exception)
A state change (for example of a class property)
A third party system called (E-Mail service)
The entry point is usually a function call.
I was now eager to try this in one of my examples and I was successful. But for a price that I cannot accept. My tests are a huge amount of functions and I would like to get your opinion about them.
The test class I want to use is easy:
public class RoleAssignement
{
public string RoleId { get; }
public string EnterpriseId { get; }
public List<string> SiteIds { get; }
public RoleAssignement(string roleId, string enterpriseScopeId)
{
Ensure.ThrowIfNull(roleId);
Ensure.ThrowIfNull(enterpriseScopeId);
Ensure.ThrowIfIdNotValid(roleId);
Ensure.ThrowIfIdNotValid(enterpriseScopeId);
RoleId = roleId;
EnterpriseId = enterpriseScopeId;
}
public RoleAssignement(string roleId, List<string> siteScopeIds)
{
Ensure.ThrowIfNull(roleId);
Ensure.ThrowIfNull(siteScopeIds);
Ensure.ThrowIfIdNotValid(roleId);
foreach(var id in siteScopeIds)
{
Ensure.ThrowIfIdNotValid(id);
}
RoleId = roleId;
SiteIds = siteScopeIds;
}
}
You can see that I have just three properties. One of them (RoleId) must be set always. The other two parameters should be exclusively set (if one is null, the other must be set and vice versa).
In the language of the book I have two "entry points" - my two constructors.
But I have ten exit points that are:
1 If roleId is null for the first constructor, an exception should be thrown.
2 If roleId is null for the second constructor, an exception should be thrown.
3 If enterpriseScopeId is null for the first constructor, an exception should be thrown.
4 If siteScopeId is null for the second constructor, an exception should be thrown.
5, 6, 7, 8 If any of the four parameters have an invalid id, an exception should be thrown.
9 If the first constructor was called with the correct parameters, RoleId and EnterpriseId should be set but SiteIds should be null.
10 If the second constructor was called => vice versa.
If I write my unit tests now, I get a long list of testing functions - one of each exit point. I pasted this in the end of my question.
The thing is: Am I really on the right way here? I have a very easy test class now and the tests for it seem to explode in a huge jungle of tests.
Testing each possible exit point with its own function will slow me down in my coding and because the tests are testing such an easy behaviour they are also worthless for me.
Or are they?
But what will happen if I start to test the more complicated things? I will have a project with 1000 lines of production code and 10000 lines of tedious test functions.
I think I misunderstood something, but I don't know what I misunderstood. Or am I okay with my tests and I have to live with this from now?
Here is my testing code - all tests are passing. I even wrote them following TDD:
Testing code: ~100 lines
Production code: ~30 lines
Really?
using CP.Admin.Core.SDK.ValueObjects;
using DataHive.Validations.Exceptions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
namespace CP.Admin.Tests
{
[TestClass]
public class RoleAssignementTests
{
[TestMethod]
public void RoleAssignementFirst_NullRoleIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
var roleAssignement = new RoleAssignement(null, "62500ac55988223c8b9b28fc");
};
Assert.ThrowsException<ArgumentNullException>(useConstructor);
}
[TestMethod]
public void RoleAssignementFirst_InvalidRoleIdParameter_ThrowsIdNotValidException()
{
Action useConstructor = () =>
{
var roleAssignement = new RoleAssignement("invalidId", "62500ac55988223c8b9b28fc");
};
Assert.ThrowsException<IdNotValidException>(useConstructor);
}
[TestMethod]
public void RoleAssignementFirst_NullEnterpriseScopeIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
string param = null;
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
};
Assert.ThrowsException<ArgumentNullException>(useConstructor);
}
[TestMethod]
public void RoleAssignementFirst_InvalidEnterpriseScopeIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", "invalidId");
};
Assert.ThrowsException<IdNotValidException>(useConstructor);
}
[TestMethod]
public void RoleAssignementSecond_NullRoleIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
var param = new List<string> { "62500ac55988223c8b9b28fc" };
var roleAssignement = new RoleAssignement(null, param);
};
Assert.ThrowsException<ArgumentNullException>(useConstructor);
}
[TestMethod]
public void RoleAssignementSecond_InvalidRoleIdParameter_ThrowsIdNotValidException()
{
Action useConstructor = () =>
{
var param = new List<string> { "62500ac55988223c8b9b28fc" };
var roleAssignement = new RoleAssignement("invalidId", param);
};
Assert.ThrowsException<IdNotValidException>(useConstructor);
}
[TestMethod]
public void RoleAssignementSecond_NullSiteScopeIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
List<string> param = null;
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
};
Assert.ThrowsException<ArgumentNullException>(useConstructor);
}
[TestMethod]
public void RoleAssignementSecond_InvalidSiteScopeIdParameter_ThrowsIdNotValidException()
{
Action useConstructor = () =>
{
var param = new List<string> { "invalidId" };
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
};
Assert.ThrowsException<IdNotValidException>(useConstructor);
}
[TestMethod]
public void RoleAssignementFirst_ParametersAreOkay_AllValuesAreCorrect()
{
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", "62500ac55988223c8b9b28fc");
Assert.IsNotNull(roleAssignement.RoleId);
Assert.IsNotNull(roleAssignement.EnterpriseId);
Assert.IsNull(roleAssignement.SiteIds);
}
[TestMethod]
public void RoleAssignementSecond_ParametersAreOkay_AllValuesAreCorrect()
{
var param = new List<string> { "62500ac55988223c8b9b28fc" };
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
Assert.IsNotNull(roleAssignement.RoleId);
Assert.IsNotNull(roleAssignement.SiteIds);
Assert.IsNull(roleAssignement.EnterpriseId);
}
}
}
As you recognize, going down this road will be very painful. Because wanting to assert for each possible case (every parameter value + every possible combination) will require (as you saw) more work than making the actual production code to work.
All of this because you are orienting tests regarding data.
If you consider testing the behavior of the system instead, you can break free from a lot of implementation details and focus on a higher level.
Considering behavior, the only one that I can eventually see is
The other two parameters should be exclusively set (if one is null, the other must be set and vice versa).
It corresponds to scenarii 9 and 10 according to your numerotation:
[TestMethod]
public void RoleAssignementFirst_ParametersAreOkay_AllValuesAreCorrect()
{
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", "62500ac55988223c8b9b28fc");
Assert.IsNotNull(roleAssignement.RoleId);
Assert.IsNotNull(roleAssignement.EnterpriseId);
Assert.IsNull(roleAssignement.SiteIds);
}
[TestMethod]
public void RoleAssignementSecond_ParametersAreOkay_AllValuesAreCorrect()
{
var param = new List<string> { "62500ac55988223c8b9b28fc" };
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
Assert.IsNotNull(roleAssignement.RoleId);
Assert.IsNotNull(roleAssignement.SiteIds);
Assert.IsNull(roleAssignement.EnterpriseId);
}
Now the test codebase has a significant smaller proportion than before comparing to the production codebase, which is a better compromise because it tests the most important thing at a greatly reduced price (both in implementation and maintenance).
Going further
Let me allow you to see something that you may never has thought would be possible. RoleAssignment could require no tests and still enforce the same rules as the one you want by better using the type system.
Consider the following code:
public class RoleAssignement
{
public Id RoleId { get; }
public Either<Id, List<Id>> RelatedIds { get; }
public RoleAssignement(Id roleId, Either<Id, List<Id>> relatedIds)
{
RoleId = roleId;
RelatedIds = relatedIds;
}
}
I used a pattern called Value Object to get rid of primitive types. These value objects (Id and Either) encapsulate all the validation for a Id to be considered valid. When given to RoleAssignement constructor, you then know for sure that you are handling correct values. No more tests needed for RoleAssignement, the type system already enforce your constraints !
You can then extract tests from your scenarii to test only value object construction once. Which means that even if Id is used everywhere through the codebase, it requires only to test once.

Testing a property set to an instance of a new object in Rhino Mocks 3.4.0

Background
I'm fixing unit tests which have been neglected for a long time for legacy code in our organisation. They're written using Rhino Mocks 3.4.0, and I'm struggling to find a way of making this test pass. Rhino Mocks documentation seems to have gone, and most answers here and blogs seem to be using updated 3.5 and 3.6 syntax.
I'm wary of updating the version of Rhino Mocks we're using, as we have several thousand unit tests which may or may not need updated if we update.
The scenario:
We have a Presenter and a View. When the Presenter is initialised, it sets some default filter properties in the View. In the past, both of these properties were enums and the test passed.
The last change updated one of the properties to be an instance of a class. The test was updated to expect a call to a static method which creates an instance with default values (matching the code under test), but the test now fails with the error Rhino.Mocks.Exceptions.ExpectationViolationException : Unordered method call.
Some sample code:
public enum FilterOptions { OptionA, OptionB, OptionC }
public class OtherFilterOptions
{
public bool Filter1 { get; set;}
public bool Filter2 { get; set; }
public OtherFilterOptions(bool filter1 = true, bool filter2 = false)
{
Filter1 = filter1;
Filter2 = filter2;
}
public static OtherFilterOptions DefaultFilterOptions()
{
return new OtherFilterOptions();
}
}
public interface IToTestView
{
FilterOptions Property1 { set; }
OtherFilterOptions Property2 { set; }
}
public class ToTestPresenter
{
public IToTestView View { get; set; }
public ToTestPresenter(IToTestView view)
{
View = view;
}
public void InitialiseView()
{
View.Property1 = FilterOptions.OptionA;
View.Property2 = OtherFilterOptions.DefaultFilterOptions();
}
}
And a failing test:
[TestFixture]
class Tests
{
[Test]
public void TestOne()
{
var mocks = new MockRepository();
var mockView = mocks.CreateMock<IToTestView>();
ToTestPresenter presenter = new ToTestPresenter(mockView);
using (mocks.Ordered())
{
mockView.Property1 = FilterOptions.OptionA;
mockView.Property2 = OtherFilterOptions.DefaultFilterOptions();
}
mocks.ReplayAll();
presenter.InitialiseView();
mocks.VerifyAll();
}
}
The full error is
Rhino.Mocks.Exceptions.ExpectationViolationException : Unordered method call! The expected call is: 'Ordered: { IToTestView.set_Property2(RhinoMocksTestApp.OtherFilterOptions); }' but was: 'IToTestView.set_Property2(RhinoMocksTestApp.OtherFilterOptions);'
I'm assuming that the test is failing because the value to be set is a method call rather than a concrete value. I've tried declaring a variable using mockView.Property2 = theVariable, but there's no change to the error.
Can I set an expectation that Property2 will be set to {some object with Values Filter1 = true, Filter2 = false}? I've seen examples doing similarly using Rhino Mocks 3.6, but is anything available using 3.4.0?
Edit:
As an example, this is an example test which passes in Rhino Mocks 3.6.1 - I'm hoping to find some syntax that works similarly for 3.4.0, if it exists.
[Test]
public void TestOne()
{
var mocks = new MockRepository();
var mockView = MockRepository.GenerateMock<IToTestView>();
ToTestPresenter presenter = new ToTestPresenter(mockView);
mocks.ReplayAll();
presenter.InitialiseView();
mockView.AssertWasCalled(v => v.Property1 = FilterOptions.OptionA);
mockView.AssertWasCalled(v => v.Property2 = Arg<OtherFilterOptions>.Matches(filters =>
(filters.Filter1 == true) && (filters.Filter2 == false)));
}
The answer I was looking for was in the LastCall.Constraints() method. Passing arguments to Constraints allows you to specify property values of an argument:
[Test]
public void TestOne()
{
var mocks = new MockRepository();
var mockView = mocks.CreateMock<IToTestView>();
ToTestPresenter presenter = new ToTestPresenter(mockView);
using (mocks.Ordered())
{
mockView.Property1 = FilterOptions.OptionA;
mockView.Property2 = OtherFilterOptions.DefaultFilterOptions();
LastCall.Constraints(
Property.Value("Filter1", true)
& Property.Value("Filter2", false));
}
mocks.ReplayAll();
presenter.InitialiseView();
mocks.VerifyAll();
}
There are a large number of options that can be passed in to the Constraints() method. Details on some of them on this CodeProject page
Another option is LastCall.IgnoreArguments() if you don't care what the property is actually set to.

Unit Test for two classes inherit an Interface

I have two classes that implement an interface, but both classes have a parameter passed into the constructor to identify what class the application would need. I am trying to test one (GetAvailablity) method on (AvailablityRepoData) class when I create an instance of AvailablityRepoData I am getting an error for non-virtual method. I would really appreciate if someone can point me to the right direction.
public interface IAvailablityRepo
{
string GetAvailablity(Availablity availablity);
}
public class AvailablityRepoData: IAvailablityRepo
{
public AvailablityRepoData(string websetting) {
}
public string GetAvailablity(Availablity availablity) {
return "Data";
}
}
public class AvailablityRepoWeb:IAvailablityRepo
{
public AvailablityRepoWeb(string DataSetting) {
}
public string GetAvailablity(Availablity availablity) {
return "Web";
}
}
public class Availablity
{
public virtual string Id {
get;
set;
}
public virtual string Status {
get;
set;
}
}
var a = new Availablity() { Id = "111", Status = "A"};
Mock<IAvailablityRepo> mockRepo = new Mock<IAvailablityRepo>();
Mock<IAvailablityRepo> RepoData = new Mock<IAvailablityRepo>();
RepoData.Setup(x => x.GetAvailablity(It.IsAny<Availablity> ())).Returns("pass");
var result = RepoData.Object.GetAvailablity(a);
As has already been said in the comments, it's not clear from the code you've posted what your error is. If I copy and past it straight into visual studio (wrapping the test code in a test), the test passes fine. I'm going to suggest that when you experienced the error, you test code was actually closer to this:
[TestMethod]
public void TestMethod1() {
var a = new Availablity() { Id = "111", Status = "A" };
Mock<IAvailablityRepo> mockRepo = new Mock<IAvailablityRepo>();
Mock<AvailablityRepoData> RepoData = new Mock<AvailablityRepoData>();
RepoData.Setup(x => x.GetAvailablity(It.IsAny<Availablity>())).Returns("pass");
var result = RepoData.Object.GetAvailablity(a);
}
This results in an error when the test is run:
System.NotSupportedException:Invalid setup on a non-virtual (overridable in VB) member:
x => x.GetAvailablity(It.IsAny<Availablity>())
The difference between this test and your original test is that I've changed the Mocked type from the interface IAvailabilityRepo to AvailabilityRepoData which is the concrete class. Since Moq only supports mocking of interfaces / virtual methods it's naturally getting upset.
As has been mentioned by #prgmtc, your test as it stands doesn't really testing much of anything.
With your current code, it doesn't actually look like you need to be using Mocks at all. Something like this might be a more appropriate test:
[TestMethod]
public void TestDataRepoReturnsDataAvailability() {
var someImportantSetting = "thisShouldBeSomethingMeaningful";
var availability = new Availablity() { Id = "111", Status = "A" };
var sut = new AvailablityRepoData(someImportantSetting);
var returnedAvailability = sut.GetAvailablity(availability);
Assert.AreEqual("Data", returnedAvailability);
}
Assuming your actual code is more complex the string passed into your data repo would presumably need to be rather more meaningful...
As a general rule of thumb, you shouldn't be mocking the system under test. If you find yourself creating a mock for the system you're testing it's a good indication that you've got to much functionality in one class and/or you're trying to test the wrong thing...
As an asside, you may want to look into something like the builder pattern to create your different repos rather than passing the type into the constructor for each of the repos as you seem to be suggesting.

Rhinomocks: I can't use AssertWasCalled properly

I'm having some issues trying to use RhinoMocks to figure out if calling a method in my class under test, a certain number of other methods is being called too.
My class to be tested:
public class OrderMessageHandler : IHandleMessages<UpdateOrder>
{
public virtual IRepository Repository { get; set; }
public void Handle(UpdateOrder message)
{
if (!message.Order.Confirmed) return;
using (var om = new OperationManager())
{
try
{
om.BeginOperation();
LVR.Order.Model.OrderHeader order = ConvertToLocalOrderHeader(message.Order);
Repository.SaveUpdate(order);
om.CommitOperation();
}
catch (Exception ex)
{
om.RollbackOperation();
// other stuff here
}
}
}
internal virtual LVR.Order.Model.OrderHeader ConvertToLocalOrderHeader(Protocol.DTO.OrderHeader order)
{
// do stuff here, and call Repository.GetAll<Country>()
}
}
Here's my test method
[Fact]
public void ConvertToLocalOrderHeader_GivenConfirmedOrderMessage_CallTheConversionMethods()
{
// create a partial mock 'cause I want some of the implementation to be the true sut class
var sut = MockRepository.GeneratePartialMock<OrderMessageHandler>();
// create a stub for the repository, in order to avoid hitting the db
sut.Repository = MockRepository.GenerateStub<IRepository>();
sut.Repository.Stub(r => r.GetAll<Country>())
.Return(
new List<Country>
{
new Country {CountryID = "IT", Description = "Italy"},
new Country {CountryID = "US", Description = "United States"}
}.AsQueryable()
);
sut.Repository.Stub(r => r.SaveUpdate<OrderHeader>(Arg<OrderHeader>.Is.Anything));
// call the method I want to test
sut.Handle(new UpdateOrder
{
Order = order,
EventId = new Guid(),
EventTime = DateTime.Now
});
// verify that the method has been called (this is useless in my real test, I put it here just to understand why it doesn't work)
sut.AssertWasCalled(s => s.Handle(Arg<UpdateOrder>.Is.Anything));
// verify that an inner method (virtual) has been called during the execution of sut.handle()
sut.AssertWasCalled(s => s.ConvertToLocalOrderHeader(order));
}
In the 2 sut.AssertWasCalled calls, I receive an error Object reference not set to an instance of an object. . The reason is that sut.AssertWasCalled make a call to the method i'm verifying... thus
sut.AssertWasCalled(s => s.Handle(Arg<UpdateOrder>.Is.Anything));
calls
sut.Handle(null)
And being null the parameter the method throws an exception.
Too bad the problem is that it shouldn't re-call the method but just tell me if it has never benn called before in the test method.
What's wrong here?
Edit:
as per suggestion received in the comments, I tried a different approach (given that I don't like the expect/verify flavour). Here's the test method:
[Fact]
public void ConvertToLocalOrderHeader_GivenConfirmedOrderMessage_CallTheConversionMethods2()
{
var mocks = new MockRepository();
var sut = mocks.PartialMock<OrderMessageHandler>();
sut.Repository = mocks.Stub<IRepository>();
sut.Repository.Stub(r => r.GetAll<Country>())
.Return(
new List<Country>
{
new Country {CountryID = "IT", Description = "Italy"},
new Country {CountryID = "US", Description = "United States"}
}.AsQueryable()
);
sut.Repository.Stub(r => r.SaveUpdate<OrderHeader>(Arg<OrderHeader>.Is.Anything));
Expect.Call(() => sut.Handle(Arg<UpdateOrder>.Is.Anything));
sut.Replay();
sut.Handle(new UpdateOrder
{
Order = order,
EventId = new Guid(),
EventTime = DateTime.Now
});
mocks.VerifyAll();
}
Adn here's the error I had:
System.InvalidOperationException
Previous method 'OrderMessageHandler.get_Repository();' requires a return value or an exception to throw.
The error is thrown by the line of code
Expect.Call(() => sut.Handle(Arg<UpdateOrder>.Is.Anything));
So, no luck even with this approach...
Any other idea?
I found out what the problem was: the method ConvertToLocalOrderHeader should be declared at least protected internal in order to let Rhinomocks override it. Virtual is not enough, being the testing class a differente class.
Very easy solution for a problem that took me hours to be solved :/

Methods adapted to satisfy unit tests. This just seems wrong

I have begun to dabble in unit testing, and have created a couple of tests that test one of my presenter methods. This testing requires a mock of my data access class, and one method in particular. This is the original method from my data access class:
public IEnumerable<IArea> GetAreaList()
{
ConnectToTFSProject();
XmlNode areaNode = GetAreaNode();
List<IArea> areaList = new List<IArea>();
foreach (XmlNode node in areaNode.FirstChild.ChildNodes)
{
IArea area = new Area() { AreaName = node.Attributes["Name"].Value };
areaList.Add(area);
}
areaList.Sort();
return areaList;
}
I would like to test the presenter method with different scenarios, e.g.:
a regular list of areas
an empty list of areas
a list of areas with duplicates
a list or areas containing one empty string area
My first thought was to create a separate mock data access class for each of these scenarios. I thought this to be a little cumbersome, so I adapted the method slightly to allow the reading of different xml files, containing data specific to the current test. Here is how my mock method looks:
public IEnumerable<IArea> GetAreaList(string dataSource)
{
List<IArea> areaList = new List<IArea>();
XmlTextReader areaReader = new XmlTextReader(dataSource);
while (areaReader.Read())
{
if (areaReader.NodeType == XmlNodeType.Text)
areaList.Add(new Area() { AreaName = areaReader.Value });
}
return areaList;
}
This mock method will then be called from the PresenterTest class as follows:
[TestMethod]
public void PopulateAreaComboBox_WithValidAreaList()
{
//Act
_presenter.PopulateAreaComboBox(mockFolderPath + "MockAreaList.xml");
//Assert
Assert.AreEqual(3, _view.AreaListLoaded.Count);
}
[TestMethod]
public void PopulateAreaComboBox_WithEmptyAreaList()
{
//Act
_presenter.PopulateAreaComboBox(mockFolderPath + "MockEmptyAreaList.xml");
//Assert
Assert.AreEqual(0, _view.AreaListLoaded.Count);
}
Now, the problem I have here is that I now need to change the signature of my original method (by adding reference to the dataSource parameter):
public IEnumerable<IArea> GetAreaList(string dataSource)
Because this parameter is required only for the unit tests, the value of null is passed into this method from the real presenter class, and never used.
I know this is wrong but how should this be accomplished? Should I create a separate mock data access class that sets up each test data scenario?
I resolved this by exposing a public string (TestDataXml) in my mock data access class. I then created a new instance of the mock data access class for each test, setting this string to the location of an individual test data xml file each time:
class MockDataRetrieval : IDataRetrieval
{
public string TestDataXml { get; set; }
public IEnumerable<IArea> GetAreaList()
{
List<IArea> areaList = new List<IArea>();
XmlTextReader areaReader = new XmlTextReader(TestDataXml);
while (areaReader.Read())
{
if (areaReader.NodeType == XmlNodeType.Text)
areaList.Add(new Area() { AreaName = areaReader.Value });
}
return areaList;
}
}
To call the mock method from the PresenterTest class:
[TestMethod]
public void PopulateAreaComboBox_WithValidAreaList()
{
//Arrange
_data = new MockDataRetrieval() { TestDataXml = mockFolderPath + "MockAreaList.xml" };
_view = new MockMainForm();
_presenter = new TestCasePresenter(_view, _data);
//Act
_presenter.PopulateAreaComboBox();
//Assert
Assert.AreEqual(3, _view.AreaListLoaded.Count);
}
[TestMethod]
public void PopulateAreaComboBox_WithEmptyAreaList()
{
//Arrange
_data = new MockDataRetrieval() { TestDataXml = mockFolderPath + "MockEmptyAreaList.xml" };
_view = new MockMainForm();
_presenter = new TestCasePresenter(_view, _data);
//Act
_presenter.PopulateAreaComboBox();
//Assert
Assert.AreEqual(0, _view.AreaListLoaded.Count);
}
Ralf: Thanks for your comment. This question relates to testing the Presenter.PopulateAreaComboBox method. The GetAreaList method in this example is from the mock data access class, and simply provides the method under test with test data.

Categories

Resources